Note SpringSecurity custom authentication 2-

Custom User

Explanation

  • User names and passwords are generally stored in a database, form input username and password and check out the database of user names and passwords for comparison
  • The following examples SpringSecurity5.x

Achieve UserDetailsService Interface

@Service
public class UserService implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //此处根据用户名在数据库中查找,这里不再查找,直接返回一个org.springframework.security.core.userdetails.User对象(如果是自定义的User类,需要实现UserDetails接口)

        return new User(username,new BCryptPasswordEncoder().encode("123456"), AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}
  • AuthorityUtils.commaSeparatedStringToAuthorityList () method for simulating a privilege of admin, the method may be converted to a comma delimited string permission set (understood)
  • User authentication process
    to find the user information from the database, if it is empty, an exception is thrown, otherwise it returns a user object, again provided by the system DaoAuthenticationProvider class to compare the password is correct
  • If you write your own User entity class needs to implement UserDetails Interface

Write configuration class

@Configuration
public class BrowserSecurity extends WebSecurityConfigurerAdapter {

    //引入自定义UserDetailsService
    @Autowired
    private UserService userService;

    //加密
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    //配置内存认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //设置UserDetailsService以及密码规则
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }
}

UserDetails Interface Overview

User custom class that implements the interface, which method has the following main

  • getAuthorities () : Get the current user role information object
  • getPassword () : Gets the password for comparison with the password entered by the user
  • getUsername : Get the current user name of the user object
  • isAccountNonExpired () : whether the current user is not expired, custom logic may determine if the returns false, throws AccountExpiredException
  • isAccountNonLocked () : whether the current user is not locked, the custom logic Analyzing
  • isCredentialsNonExpired () : the current account password is not expired
  • isEnabled () : The current account is available

Custom login page

Explanation

  • In the login form is generally used in their login page
  • We need to configure the settings in SpringSecurity

A simple login page

  • In the resources / static write a login page directory
    myLogin.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>自定义登录页面登录</title>
</head>
<body>
<form action="/login" method="post">
    <div class="form">
        <h3>账户登录</h3>
        <input type="text" placeholder="用户名" name="username" required="required" /></br>
        <input type="password" placeholder="密码" name="password" required="required" />
        <button type="submit">登录</button>
    </div>
</form>
</body>
</html>

Increase the allocation on the basis of the custom user

Overall configuration is as follows:

@Configuration
public class BrowserSecurity extends WebSecurityConfigurerAdapter {

    //引入自定义UserDetailsService
    @Autowired
    private UserService userService;

    //加密
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    //配置内存认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //设置UserDetailsService以及密码规则
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }

    //配置HttpSecurity
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //授权配置
                .antMatchers("/myLogin.html").permitAll().anyRequest().authenticated()
                .and()
                //表单配置
                .formLogin().loginPage("/myLogin.html").loginProcessingUrl("/login")
                .and()
                //默认都会产生一个hiden标签 里面有安全相关的验证 防止请求伪造 这边我们暂时不需要 可禁用掉
                .csrf().disable();
    }
}

result

In addition to the login page can be accessed directly, other requests need to jump to login page after the completion of certification can be accessed


Custom logon success and failure

Modify the form login configuration

Overall configuration is as follows:

@Configuration
public class BrowserSecurity extends WebSecurityConfigurerAdapter {

    //引入自定义UserDetailsService
    @Autowired
    private UserService userService;

    //加密
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    //配置内存认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //设置UserDetailsService以及密码规则
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }

    //配置HttpSecurity
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //授权配置
                .antMatchers("/myLogin.html").permitAll().anyRequest().authenticated()
                .and()
                //表单配置
                .formLogin().loginPage("/myLogin.html").loginProcessingUrl("/login")
                .successHandler(new AuthenticationSuccessHandler() {
                    //登录成功返回一段json信息
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
                        //Authentication authentication 包含用户登录信息
                        String name = authentication.getName();
                        response.setContentType("application/json;charset=utf-8");
                        PrintWriter out = response.getWriter();
                        response.setStatus(200);
                        Map<String,Object> map = new HashMap<>();
                        map.put("status",200);
                        map.put("msg",name);
                        ObjectMapper mapper = new ObjectMapper();
                        out.write(mapper.writeValueAsString(map));
                        out.flush();
                        out.close();
                    }
                })
                .failureHandler(new AuthenticationFailureHandler() {
                    //登录失败,根据相关异常返回失败信息
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
                        response.setContentType("application/json;charset=utf-8");
                        PrintWriter out = response.getWriter();
                        response.setStatus(401);
                        Map<String,Object> map = new HashMap<>();
                        map.put("status",401);
                        if(e instanceof LockedException){
                            map.put("msg","账户被锁定");
                        }else if(e instanceof BadCredentialsException){
                            map.put("msg","账户名或密码错误");
                        }else if(e instanceof DisabledException){
                            map.put("msg","账户被禁用");
                        }else if(e instanceof AccountExpiredException){
                            map.put("msg","账户已过期");
                        }else if(e instanceof CredentialsExpiredException){
                            map.put("msg","密码已过期");
                        }else{
                            map.put("msg","登录失败");
                        }
                        ObjectMapper mapper = new ObjectMapper();
                        out.write(mapper.writeValueAsString(map));
                        out.flush();
                        out.close();
                    }
                })
                .and()
                //默认都会产生一个hiden标签 里面有安全相关的验证 防止请求伪造 这边我们暂时不需要 可禁用掉
                .csrf().disable();
    }
}

Class can also be implemented as a custom interface

  • Successful login: Implement org.springframework.security.web.authentication.AuthenticationSuccessHandler interface onAuthenticationSuccess method
@Component
public class MyAuthenticationSucessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                        Authentication authentication) throws IOException, ServletException {
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(mapper.writeValueAsString(authentication));
    }
}
  • Login failed: to achieve
    org.springframework.security.web.authentication.AuthenticationFailureHandler of onAuthenticationFailure method
@Component
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
                                        AuthenticationException exception) throws IOException {
    }
}
  • After introduction in the configuration class
    @Autowired
    private MyAuthenticationSucessHandler authenticationSucessHandler;

    @Autowired
    private MyAuthenticationFailureHandler authenticationFailureHandler;
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    http.formLogin() // 表单登录
            .successHandler(authenticationSucessHandler) // 处理登录成功
            .failureHandler(authenticationFailureHandler) // 处理登录失败 
}

result

  • login successful

  • Login failed

Guess you like

Origin www.cnblogs.com/wuba/p/11827313.html