我仍然对Spring特别是Spring安全性感到陌生。这个应用程序是Restful应用程序。
以下是来自@RestController
的代码段:
@RequestMapping(value = "/new", method = RequestMethod.POST)
@PreRegistration("new")
@ResponseBody
public ResponseEntity<Void> newUser(@RequestBody @Valid TempUser user, UriComponentsBuilder ucBuilder) {
registerService.addUser(user);
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ucBuilder.path("/register/{userName}").buildAndExpand(user.getUserName()).toUri());
return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
}
以下是来自CustomAuthenticationProvider
的代码段:
@Override
public Authentication authenticate(final Authentication authentication) throws AuthenticationException {
final String name = authentication.getName();
final String password = authentication.getCredentials().toString();
if (name.equals("admin") && password.equals("system")) {
final List<GrantedAuthority> grantedAuths = new ArrayList<>();
grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
final UserDetails principal = new User(name, password, grantedAuths);
final Authentication auth = new UsernamePasswordAuthenticationToken(principal, password, grantedAuths);
return auth;
}
else {
throw new BadCredentialsException("NOT_AUTHORIZED");
}
}
SecurityConfig:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.requestCache()
.requestCache(new NullRequestCache())
.and()
.httpBasic()
.and()
.csrf().disable();
}
我试图实现的是当CustomAuthenticationProvider
抛出异常(例如“坏凭证”或“需要完全身份验证......”)时,我想自定义响应并以JSON格式返回响应主体。
我所做的是创建一个新的异常并使用AOP调用它。但似乎没有用。我也尝试使用@ControllerAdvice
,但由于CustomAuthenticationProvider
在控制器之外(我猜),它似乎无法正常工作。
答案 0 :(得分:1)
有一个更好的方法。您应该在spring security config和class中添加authenticationEntryPoint
,它实现AuthenticationEntryPoint
接口。像这样:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.requestCache()
.requestCache(new NullRequestCache())
.and()
.httpBasic()
// --> begin change: new lines added
.and()
.exceptionHandling().authenticationEntryPoint(new AuthExceptionEntryPoint())
// <-- end change
.and()
.csrf().disable();
}
AuthExceptionEntryPoint类,用于生成使用的JSON Jackson ObjectMapper
:
public class AuthExceptionEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException)
throws IOException, ServletException {
List<String> errors = new ArrayList<>();
errors.add("Unauthorized");
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
try {
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(response.getOutputStream(), errors);
} catch (Exception e) {
throw new ServletException();
}
}
}
有关spring security配置的更多信息,请参阅Spring docs
答案 1 :(得分:0)
您可以创建一个可以捕获AccessDeniedException
的自定义过滤器,并按照以下方式在配置文件中添加ExceptionTranslationFilter
之后的过滤器:
http.addFilterAfter(customExceptionTranslationFilter, ExceptionTranslationFilter.class)
捕获异常后,您可以使用响应对象以您喜欢的方式进行响应。
然后,您还可以添加使用您可能想要在控制器中抛出的其他异常的功能。