通过前几篇的文章,
Spring Security
的认证系列基本介绍完毕,前几篇的系列文章更多的是关注
认证
本身,对一些细枝末节没有额外的展开,因此接下来的两篇文章会补充讲解一些额外的知识。
本篇文章主要扩展讲解在前后端分离的架构下,
Spring Security
该如何处理 JSON 类型的数据交互。
随着技术的发展,分工越来越明细;“让专业的人干专业的事” 是发展的主旋律。回到我们的登录认证上,即无论登录成功还是失败,服务端都返回一段 JSON 给前端,该跳转还是该展示就由前端自己决定;前端的事就让前端工程师去折腾吧~
重走登录之路
基于这一思想,我们再回过头来看看登录的流程(
认证(一):基于表单登录的认证模式
),登录的流程大致上可以分为 3 个部分,分别是: 登录前置信息封装、登录中、登录后置处理。
-
登录前置信息封装(解析前端传递的 JSON 登录信息,封装成 UsernamePasswordAuthentionToken)。
-
登录中
-
登录后置处理(登录成功或登录失败的处理方案)
登录前置信息封装
之前我们学习过,
UsernamePasswordAuthentionFilter
过滤器用以获取前端传递的登录表单信息(username、password),封装成
UsernamePasswordAuthentionToken
;具体代码如下:
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException(
"Authentication method not supported: " + request.getMethod());
}
String username = obtainUsername(request);
String password = obtainPassword(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
username, password);
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
@Nullable
protected String obtainPassword(HttpServletRequest request) {
return request.getParameter(passwordParameter);
}
@Nullable
protected String obtainUsername(HttpServletRequest request) {
return request.getParameter(usernameParameter);
}
主要关注
obtainUsername(HttpServletRequest request)
和
obtainPassword(HttpServletRequest reqeust)
这两个方法,我们可以看出 Spring Security 是通过
request.getParamter()
的方式来获取登录的参数的, 这也就不难理解为什么是
key/value
形式的登录参数了。
知道了原理之后就很简单了,我们需要做的就是:自定义一个
Filter
替代
UsernamePasswordAuthentionFilter
,获取登录参数的时候解析前端传递的 JSON 即可。
package com.kylin.demo.security.filter;
import com.google.gson.Gson;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org