使用@RestController进行Spring安全性 - JSONish CustomAuthenticationProvider响应

时间:2016-05-06 02:38:24

标签: spring spring-mvc authentication spring-security

我仍然对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在控制器之外(我猜),它似乎无法正常工作。

2 个答案:

答案 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)

捕获异常后,您可以使用响应对象以您喜欢的方式进行响应。

然后,您还可以添加使用您可能想要在控制器中抛出的其他异常的功能。