这是我的主要应用程序配置
@SpringBootApplication public class Application { public static void main(String[] args) { new SpringApplicationBuilder(Application.class) .banner((environment,aClass,printStream) -> System.out.println(stringBanner())) .run(); } }
这是我的spring security应用程序配置.
@Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) @EnableWebMvcSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private WebServiceAuthenticationEntryPoint unauthorizedHandler; @Autowired private TokenProcessingFilter authTokenProcessingFilter; @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Override protected void configure(HttpSecurity http) throws Exception { http .csrf() .disable() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // Restful hence stateless .and() .exceptionHandling() .authenticationEntryPoint(unauthorizedHandler) // Notice the entry point .and() .addFilter(authTokenProcessingFilter) // Notice the filter .authorizeRequests() .antMatchers("/resources/**","/api/auth") .permitAll() .antMatchers("/greeting") .hasRole("USER"); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("user") .password("password") .roles("USER"); } }
这是我的TokenProcessingFilter,它为我的自定义身份验证过滤器扩展了UsernamePasswordAuthenticationFilter
@Component public class TokenProcessingFilter extends UsernamePasswordAuthenticationFilter { @Override public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) throws IOException,ServletException { HttpServletRequest httpRequest = this.getAsHttpRequest(request); String authToken = this.extractAuthTokenFromRequest(httpRequest); String userName = TokenUtils.getUserNameFromToken(authToken); if (userName != null) {/* UserDetails userDetails = userDetailsService.loadUserByUsername(userName);*/ UserDetails userDetails = fakeUserDetails(); if (TokenUtils.validateToken(authToken,userDetails)) { UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails.getUsername(),userDetails.getPassword(),userDetails.getAuthorities()); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest)); SecurityContextHolder.getContext().setAuthentication(authentication); Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); } } chain.doFilter(request,response); } private HttpServletRequest getAsHttpRequest(ServletRequest request){ if (!(request instanceof HttpServletRequest)) { throw new RuntimeException("Expecting an HTTP request"); } return (HttpServletRequest) request; } private String extractAuthTokenFromRequest(HttpServletRequest httpRequest) { /* Get token from header */ String authToken = httpRequest.getHeader("x-auth-token"); /* If token not found get it from request parameter */ if (authToken == null) { authToken = httpRequest.getParameter("token"); } return authToken; } private UserDetails fakeUserDetails(){ UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken("user","password"); List<SimpleGrantedAuthority> auth= new ArrayList<>(); auth.add(new SimpleGrantedAuthority("USER")); return new User("user","password",auth); } }
但是在运行应用程序时,我遇到此异常消息.我错过了什么?
An exception occured while running. null: InvocationTargetException:
Unable to start embedded container; nested exception is
org.springframework.boot.context.embedded.EmbeddedServletContainerException:
Unable to start embedded Tomcat: Error creating bean with name
‘tokenProcessingFilter’ defined in file
[C:\Users\kyel\projects\app\target\classes\org\app\testapp\security\TokenProcessingFilter.class]:
Invocation of init method Failed; nested exception is
java.lang.IllegalArgumentException: authenticationManager must be
specified
解决方法
您需要在TokenProcessingFilter上设置AuthenticationManager.而不是在TokenProcessingFilter上使用@Component,只需在SecurityConfig中创建它.
@Bean TokenProcessingFilter tokenProcessingFilter() { TokenProcessingFilter tokenProcessingFilter = new TokenProcessingFilter(); tokenProcessingFilter.setAuthenticationManager(authenticationManager()); return tokenProcessingFilter; }
和
protected void configure(HttpSecurity http) throws Exception { ... .addFilter(tokenProcessingFilter())