SpringSecurity系列学习(一):初识SpringSecurity (5)

如果我们想自定义认证的流程,比如使用前后端分离的架构时,认证的时候不重定向到一个页面,而是使用Restful风格的接口进行认证,返回json响应。这个时候就需要我们自定义一个Filter了

在自定义这样一个Filter前,我们需要先搞清楚SpringSecurity在验证用户的时候,走的什么逻辑。

关于认证的具体源码我们之后再讨论,我只现在只需要知道在表单登录的时候,用处理登录逻辑的过滤器叫做UsernamePasswordAuthenticationFilter,其在方法attemptAuthentication中处理认证这个过程的

private String usernameParameter = "username"; private String passwordParameter = "password"; public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { //第一步:判断请求方法是不是POST,如果不是就返回一个异常 if (this.postOnly && !request.getMethod().equals("POST")) { throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod()); } else { //第二步:从HttpRequest中获得用户名和密码 String username = this.obtainUsername(request); username = username != null ? username : ""; username = username.trim(); String password = this.obtainPassword(request); password = password != null ? password : ""; //第三步:构造一个UsernamePasswordAuthenticationToken,一个更高层的安全对象,以后再说明,这里先不深究 UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); //第四步:设置setDetails,设置ip等信息 this.setDetails(request, authRequest); //最后:getAuthenticationManager是认证处理的最终的一个机制(后面说明,这里先不深究),对安全对象进行认证 return this.getAuthenticationManager().authenticate(authRequest); } } @Nullable protected String obtainPassword(HttpServletRequest request) { //从HttpRequest获取参数名为password的参数作为密码 return request.getParameter(this.passwordParameter); } @Nullable protected String obtainUsername(HttpServletRequest request) { //从HttpRequest获取参数名为username的参数作为账号 return request.getParameter(this.usernameParameter); } protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) { authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request)); }

看完这个源码,可以想到如果我们想要实现前后端分离架构的认证,也可以自定义一个过滤器,走这个认证流程,不过我们HTTP Request中传递的json中去读取用户名和密码,登陆成功返回一个json

public class RestAuthticationFilter extends UsernamePasswordAuthenticationFilter { /** * json格式: * * { * “username": "user", * "password": "12345678" * } * * @param request 请求体 * @param response 返回体 * @return Authentication * @throws AuthenticationException 认证异常 */ @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { InputStream is = null; String username = null; String password = null; try { is = request.getInputStream(); JSONObject jsonObject= JSON.parseObject(is, JSONObject.class); username = jsonObject.getString("username"); password = jsonObject.getString("password"); } catch (IOException e) { e.printStackTrace(); throw new BadCredentialsException("json格式错误,没有找到用户名或密码"); } //认证,同父类 UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); this.setDetails(request, authRequest); return this.getAuthenticationManager().authenticate(authRequest); } /** * 认证成功逻辑 */ @Override protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain, Authentication auth) throws IOException, ServletException { res.setStatus(HttpStatus.OK.value()); res.setContentType(MediaType.APPLICATION_JSON_VALUE); res.setCharacterEncoding("UTF-8"); res.getWriter().println(JSON.toJSONString(auth)); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgwzww.html