为什么这个基于令牌 Spring 的安全过滤器没有被调用?
Why does this token based Spring Security filter not get called?
我目前正在开发一个项目,其中我使用 Angular JS 和 Spring REST 服务。最近几天,我一直在尝试为系统增加一些安全性 ()。我正在实施基于令牌的安全性。
我的基本工作正常,但在完成请求时不会调用 XAuthTokenFilter。我不知道为什么,我认为这是我忽略的非常简单的事情。相关类:
XAuthTokenFilter(doFilter 不会 每个请求都被调用)
public class XAuthTokenFilter extends GenericFilterBean {
private final static String XAUTH_TOKEN_HEADER_NAME = "x-auth-token";
private UserDetailsService detailsService;
private TokenProvider tokenProvider;
public XAuthTokenFilter(UserDetailsService detailsService, TokenProvider tokenProvider) {
this.detailsService = detailsService;
this.tokenProvider = tokenProvider;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
try {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String authToken = httpServletRequest.getHeader(XAUTH_TOKEN_HEADER_NAME);
if (StringUtils.hasText(authToken)) {
String username = this.tokenProvider.getUserNameFromToken(authToken);
UserDetails details = this.detailsService.loadUserByUsername(username);
if (this.tokenProvider.validateToken(authToken, details)) {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(details, details.getPassword(), details.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(token);
}
}
filterChain.doFilter(servletRequest, servletResponse);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
XAuthTokenConfigurer
public class XAuthTokenConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
private TokenProvider tokenProvider;
private UserDetailsService detailsService;
public XAuthTokenConfigurer(UserDetailsService detailsService, TokenProvider tokenProvider) {
this.detailsService = detailsService;
this.tokenProvider = tokenProvider;
}
@Override
public void configure(HttpSecurity http) throws Exception {
XAuthTokenFilter customFilter = new XAuthTokenFilter(detailsService, tokenProvider);
http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
}
}
安全配置
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Inject
private Http401UnauthorizedEntryPoint authenticationEntryPoint;
@Inject
private UserDetailsService userDetailsService;
@Inject
private TokenProvider tokenProvider;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Inject
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/scripts/**/*.{js,html}");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.csrf()
.disable()
.headers()
.frameOptions()
.disable()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/protected/**").authenticated()
.antMatchers("/api/open/**").permitAll()
.and()
.apply(securityConfigurerAdapter());
}
private XAuthTokenConfigurer securityConfigurerAdapter() {
return new XAuthTokenConfigurer(userDetailsService, tokenProvider);
}
/**
* This allows SpEL support in Spring Data JPA @Query definitions.
*
* See https://spring.io/blog/2014/07/15/spel-support-in-spring-data-jpa-query-definitions
*/
@Bean
EvaluationContextExtension securityExtension() {
return new EvaluationContextExtensionSupport() {
@Override
public String getExtensionId() {
return "security";
}
@Override
public SecurityExpressionRoot getRootObject() {
return new SecurityExpressionRoot(SecurityContextHolder.getContext().getAuthentication()) {};
}
};
}
}
我真的不知道为什么它没有被调用,我的 url antMatcher()
语句有问题吗?
My Context 最好包括:
@Configuration
@EnableWebMvc
@Import(AppContext.class) // The context from my backend which is included as a dependency
@ComponentScan("com.example.springsecuritytest")
public class RestContext extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
WebAppInitializer
public class WebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
//RootContext
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(RestContext.class);
// Add RootContext using ContextLoaderListener
servletContext.addListener(new ContextLoaderListener(rootContext));
// Registering and mapping dispatcher servlet
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(rootContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
请查看此 git repo。我已经准备了一个非常基本的设置来测试有无 tokenAuthenticationFilter
的安全性。过滤器实现只是一个模拟,只要 header 存在,无论其值如何,都会设置有效的身份验证。另请注意两个应用程序 WebApplicationInitializers
,它们符合 Servlet 3.0
并且以编程方式配置 Servlet 容器(而不是 web.xml)。
我目前正在开发一个项目,其中我使用 Angular JS 和 Spring REST 服务。最近几天,我一直在尝试为系统增加一些安全性 (
我的基本工作正常,但在完成请求时不会调用 XAuthTokenFilter。我不知道为什么,我认为这是我忽略的非常简单的事情。相关类:
XAuthTokenFilter(doFilter 不会 每个请求都被调用)
public class XAuthTokenFilter extends GenericFilterBean {
private final static String XAUTH_TOKEN_HEADER_NAME = "x-auth-token";
private UserDetailsService detailsService;
private TokenProvider tokenProvider;
public XAuthTokenFilter(UserDetailsService detailsService, TokenProvider tokenProvider) {
this.detailsService = detailsService;
this.tokenProvider = tokenProvider;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
try {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String authToken = httpServletRequest.getHeader(XAUTH_TOKEN_HEADER_NAME);
if (StringUtils.hasText(authToken)) {
String username = this.tokenProvider.getUserNameFromToken(authToken);
UserDetails details = this.detailsService.loadUserByUsername(username);
if (this.tokenProvider.validateToken(authToken, details)) {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(details, details.getPassword(), details.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(token);
}
}
filterChain.doFilter(servletRequest, servletResponse);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
XAuthTokenConfigurer
public class XAuthTokenConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
private TokenProvider tokenProvider;
private UserDetailsService detailsService;
public XAuthTokenConfigurer(UserDetailsService detailsService, TokenProvider tokenProvider) {
this.detailsService = detailsService;
this.tokenProvider = tokenProvider;
}
@Override
public void configure(HttpSecurity http) throws Exception {
XAuthTokenFilter customFilter = new XAuthTokenFilter(detailsService, tokenProvider);
http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
}
}
安全配置
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Inject
private Http401UnauthorizedEntryPoint authenticationEntryPoint;
@Inject
private UserDetailsService userDetailsService;
@Inject
private TokenProvider tokenProvider;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Inject
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/scripts/**/*.{js,html}");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.csrf()
.disable()
.headers()
.frameOptions()
.disable()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/protected/**").authenticated()
.antMatchers("/api/open/**").permitAll()
.and()
.apply(securityConfigurerAdapter());
}
private XAuthTokenConfigurer securityConfigurerAdapter() {
return new XAuthTokenConfigurer(userDetailsService, tokenProvider);
}
/**
* This allows SpEL support in Spring Data JPA @Query definitions.
*
* See https://spring.io/blog/2014/07/15/spel-support-in-spring-data-jpa-query-definitions
*/
@Bean
EvaluationContextExtension securityExtension() {
return new EvaluationContextExtensionSupport() {
@Override
public String getExtensionId() {
return "security";
}
@Override
public SecurityExpressionRoot getRootObject() {
return new SecurityExpressionRoot(SecurityContextHolder.getContext().getAuthentication()) {};
}
};
}
}
我真的不知道为什么它没有被调用,我的 url antMatcher()
语句有问题吗?
My Context 最好包括:
@Configuration
@EnableWebMvc
@Import(AppContext.class) // The context from my backend which is included as a dependency
@ComponentScan("com.example.springsecuritytest")
public class RestContext extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
WebAppInitializer
public class WebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
//RootContext
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(RestContext.class);
// Add RootContext using ContextLoaderListener
servletContext.addListener(new ContextLoaderListener(rootContext));
// Registering and mapping dispatcher servlet
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(rootContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
请查看此 git repo。我已经准备了一个非常基本的设置来测试有无 tokenAuthenticationFilter
的安全性。过滤器实现只是一个模拟,只要 header 存在,无论其值如何,都会设置有效的身份验证。另请注意两个应用程序 WebApplicationInitializers
,它们符合 Servlet 3.0
并且以编程方式配置 Servlet 容器(而不是 web.xml)。