SpringSecurity内置的认证过滤器是基于post请求且为form表单的方式获取认证数据的,那如何接收前端Json异步提交的数据据实现认证操作呢?
显然,我们可仿照UsernamePasswordAuthentionFilter类自定义一个过滤器并实现认证过滤逻辑;
自定义认证过滤器 :
新建com.itheima.security.filter.MyUsernamePasswordAuthenticationFilter类
package com.itheima.security.filter;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.MediaType;
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.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class MyUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public static final String USERNAME_KEY = "username";
public static final String PASSWORD_KEY = "password";
/**
* 设置构造,传入自定义登录url地址
* @param defaultFilterProcessesUrl
*/
public MyUsernamePasswordAuthenticationFilter(String defaultFilterProcessesUrl) {
super(defaultFilterProcessesUrl);
}
@Override
//认证方法
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
//MediaType:请求的媒体类型
//判断请求方法必须是post提交,且提交的数据的内容必须是application/json格式的数据
if (!request.getMethod().equals("POST") ||
! (request.getContentType().equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE) || request.getContentType().equalsIgnoreCase(MediaType.APPLICATION_JSON_UTF8_VALUE))) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
//获取前端ajax传入的数据流并反序列化为HashMap对象
HashMap<String, String> userInfo = new ObjectMapper().readValue(request.getInputStream(), HashMap.class);
String username = userInfo.get(USERNAME_KEY);
username = (username != null) ? username.trim() : "";
String password = userInfo.get(PASSWORD_KEY);
password = (password != null) ? password : "";
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
//调用认证管理器进行认证
return this.getAuthenticationManager().authenticate(authRequest);
}
/**
*
* @param request
* @param response
* @param chain 过滤器链
* @param authResult 认证对象
* method.
* @throws IOException
* @throws ServletException
*/
@Override
//认证成功时的回调方法
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
User user = (User) authResult.getPrincipal();
String username = user.getUsername();
Collection<GrantedAuthority> authorities = user.getAuthorities();
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding("UTF-8");
Map<String,String> info = new HashMap<>();
info.put("msg","登陆成功");
info.put("code","1");
info.put("data","");
response.getWriter().write(new ObjectMapper().writeValueAsString(info));
}
@Override
//认证失败时的回调方法
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding("UTF-8");
Map<String,String> info = new HashMap<>();
info.put("msg","登陆失败");
info.put("code","0");
info.put("data","");
response.getWriter().write(new ObjectMapper().writeValueAsString(info));
}
}