我尝试在RESTful应用程序中通过令牌授权配置Spring Security。
我的AuthenticationFilter看起来像:
@Configurable
public class CustomTokenAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
private static final Logger logger = LoggerFactory.getLogger(CustomTokenAuthenticationFilter.class);
private final static String SECRET_KEY = "ThisIsASecretKey";
public final String HEADER_SECURITY_TOKEN = "X-Token";
@Inject
private Users usres;
public CustomTokenAuthenticationFilter(String defaultFilterProcessesUrl) {
super(defaultFilterProcessesUrl);
super.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(defaultFilterProcessesUrl));
setAuthenticationManager(new NoOpAuthenticationManager());
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws IOException,
ServletException {
String token = request.getHeader(HEADER_SECURITY_TOKEN);
logger.info("token found:" + token);
TokenInfo tokenInfo = new TokenInfo(token, SECRET_KEY);
AbstractAuthenticationToken userAuthenticationToken;
try {
userAuthenticationToken = authUserByToken(tokenInfo);
if (userAuthenticationToken == null)
throw new AuthenticationServiceException(MessageFormat.format("Error | {0}", "Bad Token"));
return userAuthenticationToken;
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
private AbstractAuthenticationToken authUserByToken(TokenInfo token) throws ParseException {
if (token == null) {
return null;
}
UserInfo userInfo = usres.findUser(token.getUsername());
ModelMapper mapper = new ModelMapper();
mapper.getConfiguration().setProvider(new UserProvider());
User userDetails = mapper.map(userInfo, User.class);
AbstractAuthenticationToken authToken = new AuthenticationToken(userDetails);
try {
return authToken;
} catch (Exception e) {
logger.error("Authenticate user by token error: ", e);
}
return authToken;
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
chain.doFilter(request, response);
}
});
super.doFilter(req, res, chain);
}
}
和Spring Security配置:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Inject
AuthenticationManager authenticationManager;
@Bean
protected AbstractAuthenticationProcessingFilter getTokenAuthFilter() throws Exception {
CustomTokenAuthenticationFilter tapf = new CustomTokenAuthenticationFilter("/api/secure-module/admin/**");
tapf.setAuthenticationManager(authenticationManager);
return tapf;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.csrf().disable().addFilterBefore(getTokenAuthFilter(), AnonymousAuthenticationFilter.class).exceptionHandling()
.authenticationEntryPoint(new RestAuthenticationEntryPoint());
}
}
它工作正常,但CustomTokenAuthenticationFilter被调用两次,我不知道为什么。有什么想法吗?
答案 0 :(得分:3)
我发现问题,它是getTokenAuthFilter方法中的@Bean注释。然后我在链中有2个注册过滤器(additionalFilters,originalChain)。
答案 1 :(得分:1)
当过滤器生成异常导致重定向到 /error 并再次触发过滤器时,我也有类似的经历。我必须指定
@Override
public void configure(WebSecurity web) throws Exception {
// ignoring security for /error
web.ignoring().antMatchers("/error");
}