带有@RestController-JSONish CustomAuthenticationProvider响应的Spring安全性

带有@RestController-JSONish CustomAuthenticationProvider响应的Spring安全性,spring,spring-mvc,authentication,spring-security,Spring,Spring Mvc,Authentication,Spring Security,我对Spring还是个新手,尤其是Spring security。此应用程序是Restful应用程序 以下是@RestController中的片段: @RequestMapping(value = "/new", method = RequestMethod.POST) @PreRegistration("new") @ResponseBody public ResponseEntity<Void> newUser(@RequestBody @Valid Te

我对Spring还是个新手,尤其是Spring security。此应用程序是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);
    }
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
在控制器之外(我猜).

您可以创建一个自定义筛选器,该筛选器可以捕获一个
AccessDeniedException
,并以以下方式将筛选器添加到配置文件中的
ExceptionTranslationFilter
之后:

http.addFilterAfter(customExceptionTranslationFilter, ExceptionTranslationFilter.class)
捕获异常后,可以使用响应对象以您希望的方式响应


然后,您还可以在控制器中添加处理其他异常的功能。

有更好的方法。您应该在spring security config and 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();

有关spring security config的更多信息,您可以在上阅读

当我添加“addFilterAfter”时,请求将永久无效。即使登录是正确的。知道吗?感谢您给出的答案。但仍然存在相同的错误。使用有效凭据登录也会触发“AuthExceptionEntryPoint”。有什么提示我可以在哪里检查以调试此问题吗?打开
org.springframework.security
包的日志记录并将其附加到问题(当有效凭据不起作用时)我试图打印authException:org.springframework.security.authentication.inficientAuthenticationException:访问此资源需要完全身份验证尝试添加
.antMatchers(“/login”).permitAll()
之后。authorizeRequests()
是安全配置(必须是登录映射的URL)我尝试在添加了.antMatchers之后访问/登录,它可以工作。-这是否意味着in仅适用于登录表单,而不适用于httpBasic?
@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();
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();
        }
    }
}