[英]Spring Security - Custom Pre Auth filter using java config
I am trying to configure a simple custom authentication filter that checks for a token on every page of the web app except the '/login' page.我正在尝试配置一个简单的自定义身份验证过滤器,用于检查 Web 应用程序除“/登录”页面之外的每个页面上的令牌。 Right now, the filter is up and running, but no matter what settings I change, the filter is being called on every page, including '/login' which I have set to permitAll().
现在,过滤器已启动并运行,但无论我更改什么设置,都会在每个页面上调用过滤器,包括我已设置为 permitAll() 的“/login”。
When I access localhost:8080/login, I expect it to not call this filter based on my configuration below, but instead it throws an exception in the filter because no session is found.当我访问 localhost:8080/login 时,我希望它不会根据我下面的配置调用此过滤器,而是在过滤器中抛出异常,因为没有找到会话。
My question is how do I limit the filter to all pages except the '/login' page?我的问题是如何将过滤器限制为除“/登录”页面之外的所有页面?
Here is my config:这是我的配置:
@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();
}
}
And here is the filter:这是过滤器:
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;
}
The below code Filters the unauthorized/Session expired requests for a particular endpoint.下面的代码过滤特定端点的未授权/会话过期请求。 The Bean should be configured along with the endpoint URL so the Auth filter will be applicable for that endpoint.
Bean 应与端点 URL 一起配置,以便 Auth 过滤器适用于该端点。 Now by doing so you can restric the filter application for only the endpoints which you want.
现在通过这样做,您可以将过滤器应用程序限制为仅用于您想要的端点。
@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;
}
Auth Filter授权过滤器
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.