【发布时间】:2016-07-13 04:32:22
【问题描述】:
我想添加一个过滤器来使用令牌对用户进行身份验证。我通过添加两个过滤器来实现这一点:
public class JwtFilter extends GenericFilterBean {
private TokenAuthenticationService authenticationService;
public JwtFilter(TokenAuthenticationService service) {
this.authenticationService = service;
}
public JwtFilter() {
}
@Override
public void doFilter(final ServletRequest request,
final ServletResponse response,
final FilterChain chain) throws IOException, ServletException {
System.out.println("JwtFilter.doFilter");
SecurityContextHolder.getContext().setAuthentication(
authenticationService.getAuthentication((HttpServletRequest) request));
chain.doFilter(request, response);
}
之后我创建了第二个过滤器,以授权用户:
public class StatelessLoginFilter extends AbstractAuthenticationProcessingFilter {
private final TokenAuthenticationService tokenAuthenticationService;
private final UserDetailsService userService;
public StatelessLoginFilter(String urlMapping, TokenAuthenticationService tokenAuthenticationService,
UserDetailsService userDetailsService, AuthenticationManager authManager) {
super(new AntPathRequestMatcher(urlMapping));
this.userService = userDetailsService;
this.tokenAuthenticationService = tokenAuthenticationService;
setAuthenticationManager(authManager);
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
System.out.println("StatelessLoginFilter.successfulAuthentication");
// Lookup the complete User object from the database and create an Authentication for it
final User authenticatedUser = (User) userService.loadUserByUsername(authResult.getName());
final UserAuthentication userAuthentication = new UserAuthentication(authenticatedUser);
// Add the custom token as HTTP header to the response
tokenAuthenticationService.addAuthentication(response, userAuthentication);
// Add the authentication to the Security context
SecurityContextHolder.getContext().setAuthentication(userAuthentication);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException {
System.out.println("StatelessLoginFilter.attemptAuthentication");
final User user = new ObjectMapper().readValue(request.getInputStream(), User.class);
final UsernamePasswordAuthenticationToken loginToken = new U
sernamePasswordAuthenticationToken(
user.getUsername(), user.getPassword());
return getAuthenticationManager().authenticate(loginToken);
}
}
这是我的安全配置:
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private TokenAuthenticationService tokenAuthenticationService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers("/user/**").authenticated()
.anyRequest().permitAll().and()
.addFilterBefore(new StatelessLoginFilter("/login", tokenAuthenticationService, userDetailsService, authenticationManager()), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JwtFilter(tokenAuthenticationService), UsernamePasswordAuthenticationFilter.class);
}
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception{
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth .inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
@Override
protected UserDetailsService userDetailsService() {
return userDetailsService;
}
}
现在,当我向“/login”发送请求时,我得到 404 错误页面。真的,我没有映射控制器,但在安全方面,安全配置中有一个 url 映射。正如我在文档中所读到的:
创建一个具有特定模式的匹配器,它将以不区分大小写的方式匹配所有 HTTP 方法。
另外,你可以看到 System.out.println() 行。我在这里设置了断点,但是执行没有到达这行。我不确定我是否正确注册了此过滤器。我的代码主要基于这个存储库:https://github.com/BranislavLazic/angular-security
【问题讨论】:
标签: spring spring-mvc spring-security jwt