![](/img/trans.png)
[英]Spring Security custom authentication filter using Java Config
[英]Spring Security - Custom Pre Auth filter using java config
我正在尝试配置一个简单的自定义身份验证过滤器,用于检查 Web 应用程序除“/登录”页面之外的每个页面上的令牌。 现在,过滤器已启动并运行,但无论我更改什么设置,都会在每个页面上调用过滤器,包括我已设置为 permitAll() 的“/login”。
当我访问 localhost:8080/login 时,我希望它不会根据我下面的配置调用此过滤器,而是在过滤器中抛出异常,因为没有找到会话。
我的问题是如何将过滤器限制为除“/登录”页面之外的所有页面?
这是我的配置:
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
private UserDetailsService userDetailsService;
private PreAuthenticatedAuthenticationProvider preAuthenticatedProvider;
public SecurityConfig() {
super();
userDetailsService = new UserDetailsServiceImpl();
UserDetailsByNameServiceWrapper<PreAuthenticatedAuthenticationToken> wrapper =
new UserDetailsByNameServiceWrapper<PreAuthenticatedAuthenticationToken>(userDetailsService);
preAuthenticatedProvider = new PreAuthenticatedAuthenticationProvider();
preAuthenticatedProvider.setPreAuthenticatedUserDetailsService(wrapper);
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(preAuthenticatedProvider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
OpenTokenRequestAuthenticationFilter filter = new OpenTokenRequestAuthenticationFilter();
filter.setAuthenticationManager(authenticationManager());
http
.addFilter(filter)
.authorizeRequests()
.antMatchers("/login").permitAll();
}
}
这是过滤器:
public class OpenTokenRequestAuthenticationFilter extends
AbstractPreAuthenticatedProcessingFilter {
/**
* logger for the class
*/
private static final Logger logger = LoggerFactory.getLogger(OpenTokenRequestAuthenticationFilter.class);
@Autowired
private ExceptionMappingAuthenticationFailureHandler authenticationFailureHandler;
@Autowired
private IOpenTokenReader openTokenReader;
private String logoutURL;
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest)request;
HttpServletResponse httpServletResponse = (HttpServletResponse)response;
super.doFilter(httpServletRequest, httpServletResponse, chain);
HttpSession session = httpServletRequest.getSession(false);
if(session != null && session.getAttribute("ssoToken") != null)
{
SsoToken ssoToken = (SsoToken)session.getAttribute("ssoToken");
httpServletResponse.addHeader("agentName", ssoToken.getName());
httpServletResponse.addHeader("agentID", ""+ssoToken.getLoginId());
}
}
/**
*
*/
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
String principal = null;
HttpSession session = null;
try {
session = request.getSession(false);
String tokenName = openTokenReader.getTokenName();
if (tokenName != null && request.getParameter(tokenName.trim()) != null && !request.getParameter(tokenName.trim()).isEmpty()) {
logger.info("Token found in request. Token Name: "+ tokenName);
SsoToken ssoToken = null;
if (session != null) {
session.invalidate();
logger.info("Invalidated old session and creating a new session since request found with new token.");
}
session = request.getSession(true);//create new session
logger.info("New session created: "+session.getId());
Agent agent = openTokenReader.getAgent();
Map result = agent.readToken(request);
if (result != null) {
principal = (String) result.get("subject");
ssoToken = new SsoToken();
ssoToken.setLogoutURL(getLogoutURL());
// ssoToken.setName((String) result.get("lastName") +", "+(String) result.get("firstName"));
ssoToken.setName((String) result.get("firstName"));
ssoToken.setAffiliate((result.get("isAffiliate") != null && !((String)result.get("isAffiliate")).trim().equals("false")) ? true : false);
if(ssoToken.isAffiliate())
ssoToken.setLoginId((String) result.get("affiliateId"));
else
ssoToken.setLoginId((String) result.get("subject"));
}
session.setAttribute("ssoToken", ssoToken);
boolean isInValidToken = hasInvalidTokenData(ssoToken);
if (isInValidToken) {
throw new PreAuthenticatedCredentialsNotFoundException("Invalid Token found in request.");
} else {
session.setAttribute("hasValidToken", true);
}
}
} catch (Exception e) {
logger.error("Exception while reading token " + e);
}
if(session == null )
throw new PreAuthenticatedCredentialsNotFoundException("No session found.");
if(session != null && session.getAttribute("hasValidToken") == null)
throw new PreAuthenticatedCredentialsNotFoundException("No attribute 'hasValidToken' found in session.");
if(session != null && session.getAttribute("hasValidToken") != null && !(Boolean) session.getAttribute("hasValidToken"))
throw new PreAuthenticatedCredentialsNotFoundException("value of attribute 'hasValidToken' is false in session.");
/*if (session == null || session.getAttribute("hasValidToken") == null || !((Boolean) session.getAttribute("hasValidToken"))){
throw new PreAuthenticatedCredentialsNotFoundException("Token not found in request.");
}*/
if(session != null && session.getAttribute("ssoToken") != null)
{
SsoToken ssoToken = (SsoToken)session.getAttribute("ssoToken");
principal = ssoToken.getLoginId();
}
return principal;
}
public boolean hasInvalidTokenData(SsoToken token) {
boolean hasInvalidTokenData = false;
if (token == null) {
hasInvalidTokenData = true;
} else {
if (StringUtils.isBlank(token.getLoginId())) {
logger.debug("Login ID was blank.");
hasInvalidTokenData = true;
}
}
if (logger.isDebugEnabled()) {
logger.debug("Exiting: hasInvalidTokenData(SsoToken)");
logger.debug("hasInvalidTokenData=|" + hasInvalidTokenData + "|");
}
return hasInvalidTokenData;
}
@Override
protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
return "";
}
/**
* @return the logoutURL
*/
public String getLogoutURL() {
return logoutURL;
}
/**
* @param logoutURL the logoutURL to set
*/
public void setLogoutURL(String logoutURL) {
this.logoutURL = logoutURL;
}
public void setAuthenticationFailureHandler(ExceptionMappingAuthenticationFailureHandler authenticationFailureHandler){
this.authenticationFailureHandler = authenticationFailureHandler;
}
public ExceptionMappingAuthenticationFailureHandler getAuthenticationFailureHandler(){
return authenticationFailureHandler;
}
下面的代码过滤特定端点的未授权/会话过期请求。 Bean 应与端点 URL 一起配置,以便 Auth 过滤器适用于该端点。 现在通过这样做,您可以将过滤器应用程序限制为仅用于您想要的端点。
@Bean
public FilterRegistrationBean<AuthFilter> filterRegistrationBean() {
FilterRegistrationBean<AuthFilter> registrationBean = new FilterRegistrationBean<>();
AuthFilter authFilter = new AuthFilter();
registrationBean.setFilter(authFilter);
// Include the URL patterns for which the Auth filter should be applicable
registrationBean.addUrlPatterns("/api/protectedendpoint/*");
return registrationBean;
}
授权过滤器
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.filter.GenericFilterBean;
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;
public class AuthFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String authHeader = httpRequest.getHeader("Authorization");
if (authHeader != null) {
String[] authHeaderArr = authHeader.split("Bearer ");
if (authHeaderArr.length > 1 && authHeaderArr[1] != null) {
String token = authHeaderArr[1];
try {
Claims claims = Jwts.parser().setSigningKey(YOUR_JWT_SECRET_KEY).parseClaimsJws(token).getBody();
httpRequest.setAttribute("email", claims.get("email").toString());
} catch (Exception e) {
httpResponse.sendError(HttpStatus.FORBIDDEN.value(), "invalid/expired token");
return;
}
} else {
httpResponse.sendError(HttpStatus.FORBIDDEN.value(), "Authorization token must be Bearer [token]");
return;
}
} else {
httpResponse.sendError(HttpStatus.UNAUTHORIZED.value(), "Authorization token must be provided");
return;
}
chain.doFilter(httpRequest, httpResponse);
}
}```
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.