Spring security自定义用户认证流程详解

2020-03-11 18:01:22王冬梅

1.自定义登录页面

(1)首先在static目录下面创建login.html

  注意:springboot项目默认可以访问resources/resources,resources/staic,resources/public目录下面的静态文件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>登录页面</title>
</head>
<body>
<form action="/auth/login" method="post">
  用户名:<input type="text" name="username">
  <br/>
  密&emsp;码:<input type="password" name="password">
  <br/>
  <input type="submit" value="登录">
</form>
</body>
</html>

(2)在spring securiy配置类中做如下配置

@Override
  protected void configure(HttpSecurity http) throws Exception {
    http.formLogin()
        // 指定自定义登录页面
        .loginPage("/login.html")
        // 登录url
        .loginProcessingUrl("/auth/login")
        .and()
        .authorizeRequests()
        // 添加一个url匹配器,如果匹配到login.html,就授权
        .antMatchers("/login.html").permitAll()
        .anyRequest()
        .authenticated()
        .and()
        // 关闭spring security默认的防csrf攻击
        .csrf().disable();
  }

(3)测试

(4)存在的问题

<1>作为可以复用的登录模块,我们应该提供个性化的登录页面,也就是说不能写死只跳转到login.html。

    此问题比较好解决,使用可配置的登录页面,默认使用login.html即可。

<2> 请求跳转到login.html登录页面,貌似没有什么问题,但作为restful风格的接口,一般响应的都是json数据格式,尤其是app请求。

    解决思想:用户发起数据请求 --> security判断是否需要身份认证 ----->跳转到一个自定义的controller方法 ------>在该方法内判断是否是html发起的请求,如果是,就跳转到login.html,如果不是,响应一个json格式的数据,说明错误信息。

自定义Controller

@Slf4j
@RestController
public class LoginController {

  /**
   * 请求缓存
   */
  private RequestCache requestCache = new HttpSessionRequestCache();

  /**
   * 重定向工具类
   */
  private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

  /**
   * 如果配置的登录页就使用配置的登录面,否则使用默认的登录页面
   */
//  @Value("${xxxx:defaultLoginPage}")
//  private String standardLoginPage;
  private String standardLoginPage = "/login.html"; // 登录页

  /**
   * 用户身份认证方法
   */
  @GetMapping("/user/auth")
  @ResponseStatus(code = HttpStatus.UNAUTHORIZED) // 返回状态
  public ResponseData login(HttpServletRequest request, HttpServletResponse response) throws IOException {
    SavedRequest savedRequest = requestCache.getRequest(request, response);
    if (savedRequest != null) {
      String targetUrl = savedRequest.getRedirectUrl();
      log.info("请求是:" + targetUrl);
      // 如果请求是以html结尾
      if (StringUtils.endsWithIgnoreCase(targetUrl, ".html")) {
        redirectStrategy.sendRedirect(request, response, standardLoginPage);
      }
    }
    return new ResponseData("该请求需要登录,js拿到我的响应数据后,是否需要跳转到登录页面你自己看着办吧?");
  }
}