如何让Spring-Security以JSON格式返回401响应?
我有一个ReST API到一个应用程序,其中所有控制器都在下找到,这些都返回JSON响应,该响应处理所有异常以映射到JSON格式的结果。/api/@ControllerAdvice
从春季4.0开始,这非常有效,现在支持在注释上进行匹配。我无法弄清楚的是如何返回401 - 未经身份验证和400 - 错误请求响应的JSON结果。@ControllerAdvice
相反,Spring只是将响应返回到容器(tomcat),该容器将其呈现为HTML。我如何拦截它并使用与我使用的相同技术呈现JSON结果。@ControllerAdvice
安全性.xml
<bean id="xBasicAuthenticationEntryPoint"
      class="com.example.security.XBasicAuthenticationEntryPoint">
  <property name="realmName" value="com.example.unite"/>
</bean>
<security:http pattern="/api/**"
               create-session="never"
               use-expressions="true">
  <security:http-basic entry-point-ref="xBasicAuthenticationEntryPoint"/>
  <security:session-management />
  <security:intercept-url pattern="/api/**" access="isAuthenticated()"/>
</security:http>
XBasicAuthenticationEntryPoint
public class XBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request,
                         HttpServletResponse response,
                         AuthenticationException authException)
            throws IOException, ServletException {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED,
                               authException.getMessage());
    }
}
我可以通过使用 直接写入输出流来解决 401,但我不确定这是最好的方法。BasicAuthenticationEntryPoint
public class XBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {
    private final ObjectMapper om;
    @Autowired
    public XBasicAuthenticationEntryPoint(ObjectMapper om) {
        this.om = om;
    }
    @Override
    public void commence(HttpServletRequest request,
                         HttpServletResponse response,
                         AuthenticationException authException)
            throws IOException, ServletException {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        om.writeValue(httpResponse.getOutputStream(),
                      new ApiError(request.getRequestURI(),
                      HttpStatus.SC_UNAUTHORIZED,
                      "You must sign in or provide basic authentication."));
    }
}
我还没有弄清楚如何处理400,我曾经尝试过一个捕获所有控制器,它确实有效,但似乎有时它会与其他控制器有奇怪的冲突行为,我不想重新审视。
我的实现有一个陷阱,如果spring为错误请求(400)抛出任何异常,它应该在理论上捕获它,但它不会:ControllerAdvice
@ControllerAdvice(annotations = {RestController.class})
public class ApiControllerAdvisor {
    @ExceptionHandler(Throwable.class)
    public ResponseEntity<ApiError> exception(Throwable exception,
                                              WebRequest request,
                                              HttpServletRequest req) {
        ApiError err = new ApiError(req.getRequestURI(), exception);
        return new ResponseEntity<>(err, err.getStatus());
    }
}
 
					 
				 
				    		 
				    		 
				    		 
				    		