我在Spring Boot 1.5.3中有api应用程序,我使用安全性登录并通过令牌验证每个请求到我的api。我想在未通过令牌找到用户时添加我的自定义异常和未经授权的异常。添加了带异常的类,但每个响应都有500个代码,但我想要401响应代码。下面是我的代码。
StatelessAuthenticationFilter
public class StatelessAuthenticationFilter extends GenericFilterBean {
private final TokenAuthenticationService tokenAuthenticationService;
public StatelessAuthenticationFilter(TokenAuthenticationService taService) {
this.tokenAuthenticationService = taService;
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
SecurityContextHolder.getContext().setAuthentication(tokenAuthenticationService.getAuthentication((HttpServletRequest) req));
chain.doFilter(req, res);
}
StatelessLoginFilter
public class StatelessLoginFilter extends AbstractAuthenticationProcessingFilter {
private final TokenAuthenticationService tokenAuthenticationService;
private final UserServiceImpl userService;
public StatelessLoginFilter(String urlMapping, TokenAuthenticationService tokenAuthenticationService,
UserServiceImpl userDetailsService, AuthenticationManager authManager) {
super(new AntPathRequestMatcher(urlMapping));
this.userService = userDetailsService;
this.tokenAuthenticationService = tokenAuthenticationService;
setAuthenticationManager(authManager);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
String headerCredentials = request.getHeader("BasicAuth");
if (headerCredentials == null) {
throw new BadCredentialsException("No header in request");
}
String credentials = new String(Base64.decodeBase64(headerCredentials), "UTF-8");
if (!credentials.contains((":"))) {
throw new BadCredentialsException("Wrong header");
}
String [] credentialsArray = credentials.split(":");
String login = credentialsArray[0];
String password = credentialsArray[1];
final UsernamePasswordAuthenticationToken loginToken = new UsernamePasswordAuthenticationToken(login, password);
return getAuthenticationManager().authenticate(loginToken);
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
FilterChain chain, Authentication authentication) throws IOException, ServletException {
// Lookup the complete User2 object from the database and create an Authentication for it
final User authenticatedUser = userService.loadUserByUsername(authentication.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);
}
MyOwnException
public class MyOwnException extends RuntimeException {
public MyOwnException(String message) {
super(message);
}
RestResponseEntityExceptionHandler
@ControllerAdvice
public class RestResponseEntityExceptionHandler extends DefaultHandlerExceptionResolver {
@ExceptionHandler(MyOwnException.class)
void handleMyOwnException(HttpServletResponse response) throws IOException {
response.sendError(HttpStatus.UNAUTHORIZED.value());
}
}
StatelessAuthenticationSecurityConfig
@EnableWebSecurity
@Configuration
@Order(1)
public class StatelessAuthenticationSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserServiceImpl userService;
@Autowired
private TokenAuthenticationService tokenAuthenticationService;
public StatelessAuthenticationSecurityConfig() {
super(true);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().hasRole("USER")
.anyRequest().hasRole("ADMIN").and()
// custom JSON based authentication by POST of {"username":"<name>","password":"<password>"} which sets the token header upon authentication
.addFilterBefore(new StatelessLoginFilter("/login", tokenAuthenticationService, userService, authenticationManager()), UsernamePasswordAuthenticationFilter.class)
// custom Token based authentication based on the header previously given to the client
.addFilterBefore(new StatelessAuthenticationFilter(tokenAuthenticationService), UsernamePasswordAuthenticationFilter.class);
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder());
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.addAllowedOrigin("*");
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "DELETE", "OPTIONS"));
configuration.setExposedHeaders(Arrays.asList("x-auth-token"));
configuration.addAllowedHeader("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Override
protected UserServiceImpl userDetailsService() {
return userService;
}
VoteApp
@SpringBootApplication
public class VoteApp {
public static void main(String[] args) {
SpringApplication.run(VoteApp.class, args);
}
@Bean
public Filter characterEncodingFilter() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
return characterEncodingFilter;
}
}
UserServiceImpl
@Service
public class UserServiceImpl实现org.springframework.security.core.userdetails.UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public final User loadUserByUsername(String username) throws UsernameNotFoundException {
final User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("user not found");
}
return user;
}
public User findByToken(String token) throws MyOwnException {
final User user = userRepository.findByToken(token);
if (user == null) {
throw new MyOwnException("user by token not found");
}
return user;
}
public void save(User user) {
userRepository.save(user);
}
}
答案 0 :(得分:0)
将@ResponseStatus注释添加到控制器建议的异常处理程序中。
有关详细信息,请访问 - Exception Handling in Spring MVC
答案 1 :(得分:0)
显然@ControllerAdvice
无法处理您的异常,因为尚未调用控制器方法。我的意思是你在servlet过滤器中抛出异常。我想你必须手动捕捉它,像这样:
public class StatelessAuthenticationFilter extends GenericFilterBean {
private final TokenAuthenticationService tokenAuthenticationService;
public StatelessAuthenticationFilter(TokenAuthenticationService taService) {
this.tokenAuthenticationService = taService;
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
Authentication auth = null;
try {
auth = tokenAuthenticationService.getAuthentication((HttpServletRequest) req);
} catch (MyOwnException e) {
SecurityContextHolder.clearContext();
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
return;
}
SecurityContextHolder.getContext().setAuthentication(auth);
chain.doFilter(req, res);
}