java如何在身份验证后调用控制器方法
我在控制器中有以下方法:
@PostMapping(path = "/api/users/login", consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE)
@ResponseStatus(OK)
public TokenResponse login(@RequestBody LoginUserRequest loginUserRequest, Principal principal) {
return new TokenResponse().setAccessToken("token");
}
这里是一个WebSecurityConfigurerAdapter
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.formLogin().disable()
.authorizeRequests().antMatchers("/api/users/login").permitAll()
.and()
.authorizeRequests().antMatchers("/api/**").authenticated()
.and()
.addFilterBefore(mobileAuthenticationFilter(objectMapper), UsernamePasswordAuthenticationFilter.class)
.addFilter(new JwtAuthorizationFilter(authenticationManager(), super.userDetailsService()));
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("SELECT login, pass, active FROM users WHERE login = ?")
.authoritiesByUsernameQuery("SELECT login, 'ROLE_USER' FROM users WHERE login = ?")
.passwordEncoder(new CustomPasswordEncoder());
}
@Bean
public MobileAuthenticationFilter mobileAuthenticationFilter(ObjectMapper objectMapper) throws Exception {
MobileAuthenticationFilter mobileAuthenticationFilter = new MobileAuthenticationFilter(objectMapper);
mobileAuthenticationFilter.setAuthenticationManager(authenticationManager());
mobileAuthenticationFilter.setAuthenticationSuccessHandler((request, response, authentication) -> {
System.out.println(request);
});
return mobileAuthenticationFilter;
}
MobileAuthenticationFilter
正在读取json正文并准备UsernamePasswordAuthenticationToken
public class MobileAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
private final ObjectMapper objectMapper;
public MobileAuthenticationFilter(ObjectMapper objectMapper) {
super(new AntPathRequestMatcher("/api/users/login"));
this.objectMapper = objectMapper;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
BufferedReader reader = request.getReader();
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
reader.mark(0);
LoginUserRequest loginUserRequest = objectMapper.readValue(sb.toString(), LoginUserRequest.class);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(loginUserRequest.getLogin(), loginUserRequest.getPassword());
return getAuthenticationManager().authenticate(token);
} catch (IOException e) {
throw new IllegalArgumentException(e.getMessage());
}
}
}
这段代码很好用,但这是我想归档的一件事
成功身份验证后,响应将立即由:
mobileAuthenticationFilter.setAuthenticationSuccessHandler((request, response, authentication) -> {
System.out.println(request);
});
当然,在这里我可以向客户机(在主体中)返回一些东西,但是否有可能调用控制器方法public TokenResponse login
,并且该方法应该返回一个响应(基于http代码的方法契约和注释)
在那个场景中,控制器中的这个方法永远不会被调用
# 1 楼答案
如果有formLogin,你可以使用
successHandler(...)
重定向到你想要的页面。请注意,您还必须考虑错误响应由于您已明确禁用了formLogin,我建议用户调用/api/users/login,而不是在
attemptAuthentication(...)
中对其进行身份验证因此,正如您所说
..addFilterBefore(mobileAuthenticationFilter(objectMapper), UsernamePasswordAuthenticationFilter.class)
,您的过滤器将被触发以填充结果响应您的控制器将如下所示: