SpringSecurity中,自定义了TokenAuthenticationFilter继承OncePerRequestFilter之后,访问Controller后,该过滤器会被调用两次
@Slf4j
@Component
public class TokenAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private RedisCache redisCache;
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
System.out.println(httpServletRequest.getMethod());
System.out.println(httpServletRequest);
System.out.println("a");
//登录接口,直接放行
// if (httpServletRequest.getRequestURI().equals(SecurityConst.LOGIN_PATH)) {
// filterChain.doFilter(httpServletRequest, httpServletResponse);
// return;
// }
// 获取请求头中的token信息
// String token = httpServletRequest.getHeader(SecurityConst.TOKEN_ATTRIBUTE);
// //不为空,解析token
// String username = JwtUtil.getUserName(token);
// //存储认证信息
// UsernamePasswordAuthenticationToken authenticationToken =
// new UsernamePasswordAuthenticationToken(username, null, null);
// SecurityContextHolder.getContext().setAuthentication(authenticationToken);
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}
密码校验过滤器
package com.cll.jtool.security.core;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cll.jtool.common.util.JwtUtil;
import com.cll.jtool.security.constant.SecurityConst;
import com.cll.jtool.security.domain.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import nonapi.io.github.classgraph.json.JSONUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.Map;
/**
* 自定义认证过滤器
*/
@Component
@Slf4j
public class LoginAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
public LoginAuthenticationFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}
/**
* 尝试认证,可以将用户名和密码从请求中解析出来
*
* @param request from which to extract parameters and perform the authentication
* @param response the response, which may be needed if the implementation has to do a
* redirect as part of a multi-stage authentication process (such as OpenID).
* @return
* @throws AuthenticationException
*/
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
User user = null;
// try {
// //避免修改原来的流对象,这里先序列化再反序列化
// user = new ObjectMapper().readValue(request.getInputStream(), User.class);
// } catch (Exception e) {
// log.info("异常消息;{}",e.getMessage());
// throw new RuntimeException("用户名密码获取错误");
// }
user = new User();
user.setPassword("admin");
user.setUsername("admin");
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
//拿到认证信息,去认证
return this.getAuthenticationManager().authenticate(usernamePasswordAuthenticationToken);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest servletRequest = (HttpServletRequest) request;
HttpServletResponse servletResponse = (HttpServletResponse) response;
Authentication authentication = this.attemptAuthentication(servletRequest, servletResponse);
if (authentication != null) {
this.successfulAuthentication(servletRequest, servletResponse, chain, authentication);
} else {
// this.unsuccessfulAuthentication(servletRequest, servletResponse, null);
}
chain.doFilter(request,response);
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws ServletException, IOException {
super.successfulAuthentication(request, response, chain, authResult);
String username = (String) authResult.getPrincipal();
String token = JwtUtil.createJWT(username);
}
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
super.unsuccessfulAuthentication(request, response, failed);
}
}
第一次调用访问道Controller后,该过滤器又会被调用一次,并且第二次的方法类型为GET,