【发布时间】:2016-04-21 12:36:20
【问题描述】:
我正在尝试配置一个简单的自定义身份验证过滤器,用于检查 Web 应用程序的每个页面上的令牌,但“/login”页面除外。现在,过滤器已启动并运行,但无论我更改什么设置,都会在每个页面上调用过滤器,包括我设置为 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;
}
【问题讨论】:
-
不确定这是否重要,但您可以在将过滤器添加到 http 对象之前尝试插入 .authenticationProvider(preAuthenticatedProvider) 吗?我也喜欢通过“.anyRequest().authenticated();”最后是为了很好的衡量。第一个匹配的模式总是会被调用,所以你的 /login 模式仍然应该首先被命中。
-
所以当我注释掉我的自定义过滤器时这很有效,但我的最终目标是在访问除“/登录”之外的任何资源时运行过滤器,我还没有弄清楚跨度>
-
如果您删除整个 configureGlobal 方法并使用 HttpSecurity 对象添加过滤器和身份验证提供程序会怎样:http.csrf().disable().authenticationProvider(authProvider).addFilter(preAuthFilter) .. ...
标签: java spring spring-security filter