• springsecurity


    springsecurity

    一个安全框架,例如:在进行登录之前,会进行一个拦截,经过安全框架之后,才会跳转到原本要登录的地址
    culr:(不细写,需另找文档)
    可以进行登录的操作(在githbash这种中,即git的自带客户端),比如:culr http://localhost:8080/admin

    springboot整合springsecurity框架:添加springsecurity框架的pom坐标,创建一个controller就行了,然后访问这个控制层中的地址,然后会发现先跳转到了springsecurity的登录页面,然后经过用户名密码(有默认密码,也可以在yml文件中指定用户名和密码)的验证之后,就会进行跳转到原本的地址
    yml文件:

    server:
      port: 8080
    spring:
      security:
        user:
          password: 123456
          name: u
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    原本打算访问的地址:http://localhost:8080/adm/ge
    自动进行跳转到另一个地址:http://localhost:8080/login
    springsecurity的默认登录验证如图所示:
    在这里插入图片描述
    登录验证成功之后就跳转到原本的地址上:
    在这里插入图片描述
    断言,即assert():
    assertTrue():断定括号中为true,如错误,则报错
    作用:快速筛选

    自定义Config中进行设置:

    config文件:创建新的用户,并且代替了yml文件中配置用户的账号密码的作用

    package com.example.config;
    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.crypto.password.NoOpPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.security.provisioning.InMemoryUserDetailsManager;
    
    /**
     * 给用户(url)授权
     * 判断密码的正确性
     * 账号密码输入正确之后就是认证成功了
     */
    @Slf4j
    @Configuration
    public class MySecurityConfig {
        @Bean
        //返回UserDetailsService
        public UserDetailsService userDetailsService() {
            System.out.println("++++++++++++++++++");
    //        手动创建两个新用户(角色)
        /**
         *必须得给角色添加权限,否则运行失败
         */
    //    授权方式有两种: roles():会自动在参数前面添加 ROLE_
    //    authorities(): 参数写的啥就是啥
    //        两者之间,谁放在最后,谁就生成
            UserDetails user=User.builder().username("aa").password(passwordEncoder().encode("1")).roles("aa:st").authorities("aa:st","aa:ts").build();
            UserDetails user1=User.builder().username("bb").password(passwordEncoder().encode("2")).roles("te").build();
    
            InMemoryUserDetailsManager manager=new InMemoryUserDetailsManager();
    //        判断网页上输入的用户名和密码是否正确,即和上面新添加的数据进行对比
            manager.createUser(user);
            manager.createUser(user1);
            log.info(manager.toString());
            return manager;
        }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    会报错,因为,springsecurity会强制使用密码器进行密码加密
    于是手动添加一个加密器,但是可以选择空密码器(并不会真正对密码进行加密),密码器有很多种,这里使用空密码器:

    package com.example.config;
    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.crypto.password.NoOpPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.security.provisioning.InMemoryUserDetailsManager;
    
    /**
     * 给用户(url)授权
     * 判断密码的正确性
     * 账号密码输入正确之后就是认证成功了
     */
    @Slf4j
    @Configuration
    public class MySecurityConfig {
        @Bean
        //返回UserDetailsService
        public UserDetailsService userDetailsService() {
            System.out.println("++++++++++++++++++");
    //        手动创建两个新用户(角色)
        /**
         *必须得给角色添加权限,否则运行失败
         */
    //    授权方式有两种: roles():会自动在参数前面添加 ROLE_
    //    authorities(): 参数写的啥就是啥
    //        两者之间,谁放在最后,谁就生成
            UserDetails user=User.builder().username("aa").password(passwordEncoder().encode("1")).roles("aa:st").authorities("aa:st","aa:ts").build();
            UserDetails user1=User.builder().username("bb").password(passwordEncoder().encode("2")).roles("te").build();
    
            InMemoryUserDetailsManager manager=new InMemoryUserDetailsManager();
    //        判断网页上输入的用户名和密码是否正确,即和上面新添加的数据进行对比
            manager.createUser(user);
            manager.createUser(user1);
            log.info(manager.toString());
            return manager;
        }
    
        /**
         * 指定密码器,有空密码器,BCrypt密码器等等,会对网址上输入进的密码进行密码的加密,
         * 然后上面那块的代码就会对网址上输入的加密后的密码和原本存在的密码进行对比
         * @return
         */
        @Bean
        public PasswordEncoder passwordEncoder(){
    //        return new BCryptPasswordEncoder(); 
            return NoOpPasswordEncoder.getInstance();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    创建一个Controller:

    package com.example.controller;
    
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/adm")
    public class AdminController {
        @GetMapping("/ge")
        public String AdminGet(){
            return "AdminGet Success !!";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    成功!!,和用yml文件时的一样,会进行先跳转到登陆界面,输入创建的账号密码即可

    查看用户信息(权限等等):

    三种方式:1、直接从authentication中获取用户信息即可,因为用户信息在登录之后就会自动存储到authentication中,所以可以直接在authentication中获取
    2、通过Principal来获得需要的用户信息,Authentication接口继承Principal接口
    3、通过上下文加载器来获得需要的用户信息

    package com.example.controller;
    
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.security.Principal;
    
    /**查看用户信息,当然需要先进行登录
     * 用户信息会自动的储存在Authentication中
     * Authentication和Principal是子父关系
     */
    @RestController
    @RequestMapping("/currentloginuser")
    
    public class currentLoginUserController {
    //    直接从authentication中获取用户信息即可
        @GetMapping("/getau")
        public Authentication authentication(Authentication authentication){
            return authentication;
        }
    //    通过Principal来获得需要的用户信息
        @GetMapping("/getprin")
        public Principal principal(Principal principal){
            return principal;
        }
    //    通过上下文加载器来获得需要的用户信息
        @GetMapping("/getprin2")
        public Principal principal2(){
            return SecurityContextHolder.getContext().getAuthentication();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    获取信息:三种方式得到的信息都一样

    在这里插入图片描述

    设置权限:

    其中.encode(”1“)指的是对密码1进行指定加密(由加密器完成)
    .authentication().roles(): 第一个设置权限为啥就是啥,第二个会在自动在设置的权限名前添加ROLE_字符

     UserDetails user=User.builder().username("aa")
    .password(passwordEncoder().encode("1")).roles("aa:st").authorities("aa:st","aa:ts")
    .build();
    
    • 1
    • 2
    • 3

    当两种设置权限的方法都进行了调用之后,会默认第二个进行的权限设置

    url访问时的权限设置:

    先继承web安全配置器适配器WebSecurityConfigurerAdapter,再重写configure(.........)方法,此处是针对url,http进行设置的,所以参数为HttpSecurity httpSecurity
    针对url地址可以进行设置,比如必须是某某权限的才可以进行访问某某url地址(控制层设置的路径):
    甚至不用创建用户,设置成允许任何访问

    package com.example.config;
    
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    
    
    
    /**
     * 非全局方法安全权限设置
     * 对授权的url做出权限限制,即controller层的配置
     */
    @Configuration
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        protected void configure(HttpSecurity httpSecurity) throws Exception {
            //controller的配置
            httpSecurity.authorizeRequests() //授权的请求,先请求,下面都是具体的要求
                    .anyRequest() //所有的请求
                    .permitAll(); //任何身份都以进行访问
                        httpSecurity.formLogin().permitAll(); //允许单表登录
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    除此之外还以进行,每次都需要登录,设置权限名为aa:s(先是url路劲,再是权限名)等等,看注释:

    package com.example.config;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    
    
    /**
     * 非全局方法安全权限设置
     * 对授权的url做出权限限制,即controller层的配置
     */
    @Configuration
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        protected void configure(HttpSecurity httpSecurity) throws Exception {
            //controller的配置
            httpSecurity.authorizeRequests() //授权的请求,先请求,下面都是具体的要求
                    .mvcMatchers("/adm/ge") //设置mvc路径
    //      权限判断的多种方式
    //              .access("hasAuthority('aa:st') or hasRole('aa:cc')")
    // 单个条件满足   .hasAuthority("aa:st")
    //                Any指满足括号中一个权限即可,这里只写了一个权限名
                    .hasAnyAuthority("aa:s") //满足这条权限的,即权限为此字符,就可以访问上面的mvc路径
                    .mvcMatchers("/adm/ge")
                    .hasAnyAuthority("bb:t")
                    .anyRequest(); //所有的请求
    //                .authenticated() //都要求登录
                        httpSecurity.formLogin().permitAll(); //允许单表登录
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    除此之外还有很多种匹配url路径的方法,但是不常用:

    		httpSecurity.authorizeRequests().antMatcher("");
            httpSecurity.authorizeRequests().regexMatcher("");
    
    • 1
    • 2

    .access()方法

            httpSecurity.authorizeRequests()
            .antMatchers("")
            .access("hasAnyAuthority('aa:s') or hasRole('ss')");
    
    • 1
    • 2
    • 3

    权限设置:

    hasRole() //权限名前面自动加上ROLE_
    hasAnyRole() //权限名前面自动加上ROLE_
    hasAnyAuthority()
    
    • 1
    • 2
    • 3

    具体到方法上的访问设置: 预授权(调用之前进行授权) 后授权(方法执行完成之后查看权限等)

    在方法上设置权限:满足指定的权限才可以调用当前方法

    如在方法上添加注解@PreAuthorize("hasAnyAuthority('ROLE_te')")
    这种注解的方式得先创建全局配置,再添加 同意方法安全注解@EnableMethodSecurity(proxyTargetClass = true)参数为:开启预授权

    接口,实现类,controller,全局配置config,创建用户的配置config,主方法:

    package com.example.service;
    
    public interface CoffeService {
        public String update();
        public String add();
        public String delet();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在具体的方法上面设置预授权的权限名

    package com.example.service;
    
    import org.springframework.security.access.prepost.PreAuthorize;
    import org.springframework.stereotype.Service;
    
    /**
     * 设置方法的权限,满足权限即可执行指定的方法,否则亦然
     */
    @Service
    public class CoffeServiceImpl implements CoffeService{
    
        @PreAuthorize("hasAnyAuthority('aa:st')")//预授权,只有满足条件才可以
        @Override
        public String update() {
            return "update预览";
        }
        @PreAuthorize("hasAnyAuthority('ROLE_te')")//因为最初的设置就是roles设置,这个关键字会进行自动的添加前缀role_
        @Override
        public String add() {
            return "add预览";
        }
    
        @Override
        public String delet() {
            return "delet预览";
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    package com.example.controller;
    
    import com.example.service.CoffeService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/coffe")
    public class CoffeController {
        @Autowired
        private CoffeService coffeService;
        @GetMapping("update")
        public String getupdate(){
            return coffeService.update();
        }
        @GetMapping("add")
        public String getadd(){
            return coffeService.add();
        }
        @GetMapping("delet")
        public String getdelet(){
            return coffeService.delet();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    创建用户config:

    package com.example.config;
    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.crypto.password.NoOpPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.security.provisioning.InMemoryUserDetailsManager;
    
    /**
     * 给用户(url)授权
     * 判断密码的正确性
     * 账号密码输入正确之后就是认证成功了
     */
    @Slf4j
    @Configuration
    public class MySecurityConfig {
        @Bean
        //返回UserDetailsService
        public UserDetailsService userDetailsService() {
            System.out.println("++++++++++++++++++");
    //        手动创建两个新用户(角色)
        /**
         *必须得给角色添加权限,否则运行失败
         */
    //    授权方式有两种: roles():会自动在参数前面添加 ROLE_
    //    authorities(): 参数写的啥就是啥
    //        两者之间,谁放在最后,谁就生成
            UserDetails user=User.builder().username("aa").password(passwordEncoder().encode("1")).roles("aa:st").authorities("aa:st","aa:ts").build();
            UserDetails user1=User.builder().username("bb").password(passwordEncoder().encode("2")).roles("te").build();
    
            InMemoryUserDetailsManager manager=new InMemoryUserDetailsManager();
    //        判断网页上输入的用户名和密码是否正确,即和上面新添加的数据进行对比
            manager.createUser(user);
            manager.createUser(user1);
            log.info(manager.toString());
            return manager;
        }
    
        /**
         * 指定密码器,有空密码器,BCrypt密码器等等,会对网址上输入进的密码进行密码的加密,
         * 然后上面那块的代码就会对网址上输入的加密后的密码和原本存在的密码进行对比
         * @return
         */
        @Bean
        public PasswordEncoder passwordEncoder(){
    //        return new BCryptPasswordEncoder();
            return NoOpPasswordEncoder.getInstance();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    全局配置confog:@EnableMethodSecurity()注解上有注解@Configuration,所以可以取代上面的@Configuration注解

    package com.example.config;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    
    /**
     * 全局方法安全权限设置
     */
    @Configuration
    @EnableMethodSecurity(proxyTargetClass = true)// 这里面就包含了@Configuration,所以可以取代上面的@Configuration注解
    public class GlobalSecurityConfig extends WebSecurityConfigurerAdapter {
        protected void configure(HttpSecurity http) throws Exception{
            http.authorizeRequests().anyRequest().authenticated();//所有的请求都需要认证,即就是先进行登录
            http.formLogin().permitAll();//允许单次登录
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    登录之后,访问controller路径,当权限不满足就显示403

    登录。。。。处理器返回json给前端(这里先返回到页面)

    创建处理器,在Config中配置登陆成功。。。。处理器

    package com.example.config;
    
    import com.example.handler.AppAutheticationFailedHandler;
    import com.example.handler.AppAutheticationSuccessHandler;
    import com.example.handler.AppLoginLoutSuccessHandler;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    
    /**
     * 对认证,退出,有权访问成功与否做处理
     */
    @Configuration
    public class AppAutheticationConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private AppAutheticationSuccessHandler successHandler;
        @Autowired
        private AppAutheticationFailedHandler failedHandler;
        @Autowired
        private AppLoginLoutSuccessHandler logoutsuccessHandler;
        @Override
        public void configure(HttpSecurity httpSecurity) throws Exception {
            httpSecurity.authorizeRequests().anyRequest().authenticated();
            httpSecurity.formLogin()
                                .successHandler(successHandler) //认证成功
                                .failureHandler(failedHandler)//认证失败
                    .and().logout()
                    .logoutSuccessHandler(logoutsuccessHandler); //退出成功
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    登陆成功处理器:

    package com.example.handler;
    
    import com.example.vo.HttpResult;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.Writer;
    
    /**
     * 认证成功处理器
     */
    @Component
    public class AppAutheticationSuccessHandler implements AuthenticationSuccessHandler {
        @Autowired
        private ObjectMapper objectMapper;
        @Override
        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
    //        返回的数据
            HttpResult httpResult=HttpResult.builder()
                    .message("登陆成功")
                    .code(1)
                    .build();
    //        将实体类数据转换成JSON格式数据
            String s=objectMapper.writeValueAsString(httpResult);
    //        设置响应数据
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json;charset=UTF-8");
            Writer writer = response.getWriter();
            writer.write(s);
            writer.flush();
            writer.close();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    登录失败处理器:

    package com.example.handler;
    
    import com.example.vo.HttpResult;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.web.authentication.AuthenticationFailureHandler;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.Writer;
    
    /**
     * 认证失败处理器
     */
    @Component
    public class AppAutheticationFailedHandler implements AuthenticationFailureHandler {
        @Autowired
        private ObjectMapper objectMapper;
        @Override
        public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
            //        返回的数据
            HttpResult httpResult=HttpResult.builder()
                    .message("登陆失败")
                    .code(0)
                    .build();
    //        将实体类数据转换成JSON格式数据
            String s=objectMapper.writeValueAsString(httpResult);
    //        设置响应数据
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json;charset=UTF-8");
            Writer writer = response.getWriter();
            writer.write(s);
            writer.flush();
            writer.close();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    退出成功处理器;

    package com.example.handler;
    
    import com.example.vo.HttpResult;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.*;
    
    /**
     * 退出成功处理器
     */
    @Component
    public class AppLoginLoutSuccessHandler implements LogoutSuccessHandler {
        @Autowired
        private ObjectMapper objectMapper;
        @Override
        public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
            HttpResult result=HttpResult.builder()
                    .code(1)
                    .message("logout Success")
                    .build();
            String s=objectMapper.writeValueAsString(result);
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json;charset=UTF-8");
            Writer writer=response.getWriter();
            writer.write(s);
            writer.flush();
            writer.close();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    放回的json数据的框架:

    package com.example.vo;
    
    import lombok.Builder;
    import lombok.Data;
    
    @Data
    @Builder
    public class HttpResult {
        private Integer code;
        private Object data;
        private String message;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    自定义用户信息: 将之前在config配置文件中进行的创建用户摘出来

    • 原来的config配置文件中是返回UserDetailsService类型的数据:在其中的MyUserDetails就是具体创建的用户,对应原来config配置文件中创建用户
    • 实现了UserDetailsServiceUserDetails注册为bean,代替了框架本身的bean,框架扫描新的
    package com.example.service;
    
    import com.example.vo.MyUserDetails;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.PropertySource;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.stereotype.Service;
    import org.springframework.util.StringUtils;
    
    @Slf4j
    @Service
    public class UserDetailsServiceImpl implements UserDetailsService {
    
        @Override
        public UserDetails loadUserByUsername(String uname) throws UsernameNotFoundException {
            if(!StringUtils.hasText(uname)){
                    throw new UsernameNotFoundException("用户名为空 !!");
            }
            if(!uname.equals("aa")){
                    throw new UsernameNotFoundException("用户名错误");
            }
            log.info(uname);
            MyUserDetails myUserDetails=new MyUserDetails();
    
            return myUserDetails;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    上面代码中MyUserDetails类如下:

    package com.example.vo;
    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.PropertySource;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.stereotype.Component;
    
    import java.util.Collection;
    
    @Slf4j
    @Component
    public class MyUserDetails implements UserDetails {
    
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return null;
        }
    
        @Override
        public String getPassword() {
    
            return new BCryptPasswordEncoder().encode("123456");
        }
    
        @Override
        public String getUsername() {
            return "aa";
        }
    
        @Override
        public boolean isAccountNonExpired() {
            return true;
        }
    
        @Override
        public boolean isAccountNonLocked() {
            return true;
        }
    
        @Override
        public boolean isCredentialsNonExpired() {
            return true;
        }
    
        @Override
        public boolean isEnabled() {
            return true;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    数据库取数据:

    将用户输入的密码账号与数据库中数据做对比(上面写死的):

    package com.example.demos.web.vo;
    
    import com.example.demos.web.entity.User;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    import org.springframework.security.core.userdetails.UserDetails;
    
    import java.util.Collection;
    import java.util.List;
    
    
    public class MyUserDetails implements UserDetails {
        private final User user;
        private List<SimpleGrantedAuthority> list;
        public MyUserDetails(User user){
            this.user=user;
        }
        public void setAuthorities(List<SimpleGrantedAuthority> list) {
            this.list = list;
        }
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return this.list;
        }
    
        @Override
        public String getPassword() {
            return this.user.getPassword();
        }
    
        @Override
        public String getUsername() {
            return this.user.getUsername();
        }
    
        @Override
        public boolean isAccountNonExpired() {
            return this.user.getAccountNoExpired();
        }
    
        @Override
        public boolean isAccountNonLocked() {
            return true;
        }
    
        @Override
        public boolean isCredentialsNonExpired() {
            return this.user.getCredentialsNoExpired();
        }
    
        @Override
        public boolean isEnabled() {
            return true;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    package com.example.demos.web.service.impl;
    
    import com.example.demos.web.entity.User;
    import com.example.demos.web.vo.MyUserDetails;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    @Service
    public class UserDetailsServiceImpl implements UserDetailsService {
        @Autowired
        private UserServiceImpl userService;
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 
    //        通过前端拿到username
            User user =userService.getUsernameMessage(username);
            List<SimpleGrantedAuthority> list =null;
    
            if(user==null){
                throw new UsernameNotFoundException("用户不存在" );
            }
    //
    //        user.setPassword("'"+user.getPassword()+"'");
            MyUserDetails myUserDetails=new MyUserDetails(user);
            SimpleGrantedAuthority grantedAuthority =new SimpleGrantedAuthority("将从数据库中得到的权限(现在被存了另一个类中)添加权限进SimpleGrantedAuthority类中");
            list.add(grantedAuthority);
            myUserDetails.setAuthorities(list);
            return myUserDetails;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    流程:先User user=userService.getUsernameMessage(username)获得user,然后将user中权限遍历出来,放入List list =中,再调用MyUserDetails myUserDetails=new MyUserDetails(user);,再设置myUserDetails.setAuthorities(list);,然后再将数据库中的用户密码存入user中,由此得到用户密码在数据库中的值,最后return myUserDetails;将具体数据信息和权限成功定义在Authorities中,框架自动校验

  • 相关阅读:
    代理模式 静态代理 动态代理
    Kotlin 协程之取消与异常处理探索之旅(下)
    Linux软件包管理— rpm软件包查询
    【回归预测-NN预测】基于文化算法优化神经网络实现数据回归预测附matlab代码
    odoo Web Controllers 学习总结
    SAP从放弃到入门系列之MRP中BOM的选择逻辑
    SpringCloud微服务之重要术语详解
    科目三基础四项(一)
    从“特种兵游”到Citywalk,年轻人的下一个旅游热点会在哪?
    哈夫曼树你需要了解一下
  • 原文地址:https://blog.csdn.net/prisoneradvance/article/details/133658247