SpringSecurity学习记录2

PassWordEncoder密码解析详解

BCryptPasswordEncoder类的用法  
    简介:BCryptPasswordEncoder是Spring Security官方推荐的密码解析器,平时多使用这个解析器
    BCryptPasswordEncoder是对bcrypt强散列方法的具体实现,是基于Hash算法实现的单向加密,可以通过setength控制加密强度,默认为10

        BCryptPasswordEncoder pw = new BCryptPasswordEncoder();
        //加密
        String encode = pw.encode("123");
        System.out.println(encode);   // $2a$10$iyQ1sb.sS/vxLrPo9byZSOKoy4VFLMAOmPZBvWhIps2kHGXO/wI8O
        //比较密码
        boolean matches = pw.matches("123", encode);
        System.out.println(matches);  //true

2.5 自定义登录逻辑

当进行自定义登录逻辑时需要用到之前讲解的UserDetailsService 和 PasswordEncoder 但是 Spring Security要求:当进行自定义登录逻辑时容器内必须有PasswordEncoder实例。所以不能直接new对象

2.5.1 编写配置类
@Configuration
public class SecuriytConfig {
    
    

    // 把BCryptPasswordEncoder放给了spring容器去管理
    @Bean
    public PasswordEncoder passwordEncoder() {
    
    
        return new BCryptPasswordEncoder();
    }
}

2.5.2 编写service
//实现 UserDeatailsService接口 重写 loadUserByUsername方法  在里面写逻辑
@Service
public class UserDetailServiceImpl implements UserDetailsService
{
    
    

    @Autowired
    private PasswordEncoder passwordEncoder;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    
    
        //1.根据用户名去数据库查询,如果不存在抛UsernameNotFoundException异常
        if(!"admin".equals(username)){
    
    
            throw new UsernameNotFoundException("用户不存在");

        }
        //2.比较密码(注册时已经加密过)如果匹配成功返回UserDetails
        String password = passwordEncoder.encode("123");
        return new User(username,password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin,normal"));
    }
}

2.6 自定义登录界面

虽然 Spring Security给我们提供了登录页面,但是对于实际项目中,大多喜欢使用自己的登录页面,所以Spring Security 中不仅仅提供了登录页面,还支持用户自定义登录页面。实现过程也比较简单,只需要修改配置类即可。

2.6.1 编写登录页面

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login" method="post">
    用户名:<input type="text" name="username" /> <br />
    密码:<input type="password" name="password" /> <br/>
    <input type="submit" value="登录" />
</form>
</body>
</html>
2.6.2 编写配置类
@Configuration
public class SecuriytConfig extends WebSecurityConfigurerAdapter{
    
    

    @Override
    protected  void configure(HttpSecurity http) throws  Exception{
    
    
        http.csrf().disable();

        //表单提交
        http.formLogin()
                //自定义登录页面
                .loginPage("/login.html")
                //必须和表单提交的接口一样,会去执行自定义登录逻辑
                .loginProcessingUrl("/login")
                //登录成功后跳转的页面,post请求
                .successForwardUrl("/toMain")
                .failureForwardUrl("/toError");


        //授权
        http.authorizeRequests()
                //放行 login.html  /error.html不需要认证
                .antMatchers("/login.html").permitAll()
                .antMatchers("/error.html").permitAll()
                //所有请求都必须认证才能访问,必须登录
                .anyRequest().authenticated();


    }

2.6.3 自定义设置请求账户和密码的参数

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login" method="post">
    用户名:<input type="text" name="username123" /> <br />
    密码:<input type="password" name="password123" /> <br/>
    <input type="submit" value="登录" />
</form>
</body>
</html>
@Configuration
public class SecuriytConfig extends WebSecurityConfigurerAdapter{
    
    

    @Override
    protected  void configure(HttpSecurity http) throws  Exception{
    
    
        http.csrf().disable();

        //表单提交
        http.formLogin()
                //自定义入参
            	.usernameParameter("username123")
            	.passwordParameter("password123")
                //自定义登录页面
                .loginPage("/login.html")
                //必须和表单提交的接口一样,会去执行自定义登录逻辑
                .loginProcessingUrl("/login")
                //登录成功后跳转的页面,post请求
                .successForwardUrl("/toMain")
                .failureForwardUrl("/toError");


        //授权
        http.authorizeRequests()
                //放行 login.html  /error.html不需要认证
                .antMatchers("/login.html").permitAll()
                .antMatchers("/error.html").permitAll()
                //所有请求都必须认证才能访问,必须登录
                .anyRequest().authenticated();


    }

2.6.4 自定义登录成功处理器
@Configuration
public class SecuriytConfig extends WebSecurityConfigurerAdapter{
    
    

    @Override
    protected  void configure(HttpSecurity http) throws  Exception{
    
    
        http.csrf().disable();

        //表单提交
        http.formLogin()
                //自定义登录页面
                .loginPage("/login.html")
                //必须和表单提交的接口一样,会去执行自定义登录逻辑
                .loginProcessingUrl("/login")
                //登录成功后跳转的页面,post请求
                //.successForwardUrl("/toMain")
                //自定义登录成功处理器
                .successHandler(new MyAuthenticationSuccessHandler("/main.html"))
                .failureForwardUrl("/toError");



        //授权
        http.authorizeRequests()
                //放行 login.html  /error.html不需要认证
                .antMatchers("/login.html").permitAll()
                .antMatchers("/error.html").permitAll()
                //所有请求都必须认证才能访问,必须登录
                .anyRequest().authenticated();


    }


    // 把BCryptPasswordEncoder放给了spring容器去管理
    @Bean
    public PasswordEncoder passwordEncoder() {
    
    
        return new BCryptPasswordEncoder();
    }
}

自定义类 MyAuthenticationSuccessHandler

public class MyAuthenticationSuccessHandler  implements AuthenticationSuccessHandler {
    
    
    private String url;
    public MyAuthenticationSuccessHandler (String url){
    
    
        this.url=url;
    }


    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
    
    
        User user = (User) authentication.getPrincipal();
        System.out.println(user.getUsername());
        //出于安全的考虑输出null
        System.out.println(user.getPassword());
        System.out.println(user.getAuthorities());
        httpServletResponse.sendRedirect(url);

    }
}

输出结果:

image-20201229192931516

2.6.5 自定义失败成功处理器
@Configuration
public class SecuriytConfig extends WebSecurityConfigurerAdapter{
    
    

    @Override
    protected  void configure(HttpSecurity http) throws  Exception{
    
    
        http.csrf().disable();

        //表单提交
        http.formLogin()
                //自定义登录页面
                .loginPage("/login.html")
                //必须和表单提交的接口一样,会去执行自定义登录逻辑
                .loginProcessingUrl("/login")
                //登录成功后跳转的页面,post请求
                //.successForwardUrl("/toMain")
                //自定义登录成功处理器
                .successHandler(new MyAuthenticationSuccessHandler("/main.html"))
                //.failureForwardUrl("/toError");
                //自定义失败处理器
                .failureHandler(new MyAuthenticacationFailureHandler("/error.html"));



        //授权
        http.authorizeRequests()
                //放行 login.html  /error.html不需要认证
                .antMatchers("/login.html").permitAll()
                .antMatchers("/error.html").permitAll()
                //所有请求都必须认证才能访问,必须登录
                .anyRequest().authenticated();


    }


    // 把BCryptPasswordEncoder放给了spring容器去管理
    @Bean
    public PasswordEncoder passwordEncoder() {
    
    
        return new BCryptPasswordEncoder();
    }
}

自定义类 MyAuthenticationFailureHandler

public class MyAuthenticacationFailureHandler implements AuthenticationFailureHandler
{
    
    
    private String url;
    public MyAuthenticacationFailureHandler (String url){
    
    
        this.url=url;
    }
    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
    
    
        httpServletResponse.sendRedirect(url);
    }
}

猜你喜欢

转载自blog.csdn.net/zhanduo0118/article/details/112093791