SpringSecurity前后端分离自定义登录处理

SpringSecurity前后端分离登录处理

  • 自定义登录成功处理(前后端分离开发)
    • 1.实现AuthenticationSucessHandler,自定义成功之后处理。
    • 2.配置AuthenticationSuccessHandler
    • 3.浏览器返回json格式数据
  • 显示登录失败信息
  • 自定义登录失败处理
  • 注销登录

自定义登录成功处理(前后端分离开发)

有时候页面跳转并不能满足我们,特别是在前后端分离开发中就不需要成功之后跳转页面。只需要给前端返回一个JSON通知登录成功还是失败与否。这个时候可以通过自定义AuthenticationSucccessHandler 实现。

public interface AuthenticationSuccessHandler {
    
    default void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException, ServletException {
        this.onAuthenticationSuccess(request, response, authentication);
        chain.doFilter(request, response);
    }

    void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException;
}

根据接口的描述信息,也可以得知登录成功会自动回调这个方法,进一步查看它的默认类实现,你会发现successForwardUrl、defaultSuccessUrl也是由它的子类实现的。

SpringSecurity前后端分离自定义登录处理_第1张图片

1.实现AuthenticationSucessHandler,自定义成功之后处理。

public class MyAuthenticationSuccessHandlerConfig implements AuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        Map result = new HashMap<>();
        result.put("msg","登录成功!");
        result.put("status",200);
        result.put("authentication",authentication);
        response.setContentType("application/json;charset=UTF-8");
        String string = new ObjectMapper().writeValueAsString(result);
        response.getWriter().println(string);
    }
}

2.配置AuthenticationSuccessHandler

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
               	...
                .and()
                .formLogin()
                ...
                //认证成功时处理,前后端分离解决方案
                .successHandler(new MyAuthenticationSuccessHandlerConfig())
                .and()
                //禁止 csrf 跨站请求保护
                .csrf().disable();
    }
}

3.浏览器返回json格式数据

SpringSecurity前后端分离自定义登录处理_第2张图片

显示登录失败信息

经过源码debug分析可知,Security在登录失败之后会将异常信息存储到request 作用域或者session中 key为SPRING_SECURITY_LAST_EXCEPTION常量中。

  • failureForwardUrl() forward 将信息存在request作用域中
  • failureUrl() redirect 将信息存在session作用域中

  • 显示异常信息
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>用户登录</title>
</head>
<body>
    <h2>
        <div th:text="${SPRING_SECURITY_LAST_EXCEPTION}"></div>
    </h2>
   	...
</body>
</html>

自定义登录失败处理

和自定义登录成功一样,Spring Security 同样为前后端分离开发提供了登录失败的处理,这个类就是AuthenticationFailureHandler。源码为:

public interface AuthenticationFailureHandler {

   /**
    * Called when an authentication attempt fails.
    * @param request the request during which the authentication attempt occurred.
    * @param response the response.
    * @param exception the exception which was thrown to reject the authentication
    * request.
    */
   void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
         AuthenticationException exception) throws IOException, ServletException;

}

根据接口的描述信息,也可以得知登录失败会自动回调这个方法,进一步查看它的默认实例,会发现failureUrl、failureForwardUrl也是由它的子类实现的。

AuthenticationFailureHandler关系图

SpringSecurity前后端分离自定义登录处理_第3张图片

  • 自定义AuthenticationFailureHandler实现
 public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
     @Override
     public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
         Map<String,Object> result = new HashMap<>();
         result.put("msg","登录失败!"+exception.getMessage());
         result.put("status",500);
         response.setContentType("application/json;charset=UTF-8");
         String string = new ObjectMapper().writeValueAsString(result);
         response.getWriter().println(string);
     }
 }
 
  • 配置AuthenticationFailureHandler
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
         		...
                .anyRequest().authenticated()
                .and()
                .formLogin()
            	...
                .failureHandler(new MyAuthenticationFailureHandler())
                .and()
                //禁止 csrf 跨站请求保护
                .csrf().disable();
    }
}
  • 访问登录,输入错误密码

SpringSecurity前后端分离自定义登录处理_第4张图片

注销登录

Spring Security中也提供了默认的注销登录配置,在开发时也可以按照自己需求对注销进行个性化定制。

  • 开启注销登录(默认开启)
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                ...
                .anyRequest().authenticated()
                .and()
                .formLogin()
                ...
                .and()
                .logout()
                //指定注销登录的URl,默认的请求方式是GET
                .logoutUrl("/logout")
                //是否让当前session失效
                .invalidateHttpSession(true)
                //清除认证信息
                .clearAuthentication(true)
                //注销登录跳转页面
                .logoutSuccessUrl("/login.html")
                .and()
                //禁止 csrf 跨站请求保护
                .csrf().disable();
    }
}
  • 通过logout()方法开启注销配置
  • logoutUrl指定退出登录请求地址,默认请求是GET请求,路径为/logout
  • invalidateHttpSession退出时是否是session失效,默认值为true
  • clearAuthentication 退出时是否清除认证信息,默认值为true
  • logoutSuccessUrl退出登录时跳转地址

配置多个注销登录请求

如果项目中有需要,开发者还可以配置多个注销登录的请求,同时还可以指定请求的方法:

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                ...
                .anyRequest().authenticated()
                .and()
                .formLogin()
                ...
                .and()
                .logout()
                .logoutRequestMatcher(new OrRequestMatcher(
                        new AntPathRequestMatcher("/aa","GET"),
                        new AntPathRequestMatcher("/bb","POST")
                ))
                ...
                .and()
                //禁止 csrf 跨站请求保护
                .csrf().disable();
    }
}

你可能感兴趣的:(SpringSecurity,java,springsecurity)