【问题标题】:Handle 401 Error (Spring Security)处理 401 错误(Spring Security)
【发布时间】:2015-12-11 16:25:46
【问题描述】:

我可以处理 404 错误。

@ResponseStatus(value = HttpStatus.NOT_FOUND)
    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseBody
    public void noHandlerFoundException (HttpServletResponse response) throws IOException{
       //some code
    }

但是如何处理 401 错误呢?

编辑我使用的是 Java 而不是 web.xml

编辑我应该在 NoHandlerFoundException 中放入什么来处理 HttpStatus.UNAUTHORIZED

编辑

我有方法unsuccessfulAuthentication,当认证失败时:

public class StatelessLoginFilter extends AbstractAuthenticationProcessingFilter { 

    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                                      AuthenticationException failed) throws IOException, ServletException {
                SecurityContextHolder.clearContext();

                if (logger.isDebugEnabled()) {
                    logger.debug("Authentication request failed: " + failed.toString());
                    logger.debug("Updated SecurityContextHolder to contain null Authentication");
                    logger.debug("Delegating to authentication failure handler " + failureHandler);
                }

        //        response.setCharacterEncoding("UTF-8");
        //        response.getWriter().write(jsonService.toString(jsonService.getResponse(false, "Не удалось авторизоваться", "401")));

                rememberMeServices.loginFail(request, response);
                failureHandler.onAuthenticationFailure(request, response, failed);

            }
        }

此代码发送 401 错误 html。我需要发送json,你可以在cmets中看到。

【问题讨论】:

标签: java spring spring-security


【解决方案1】:

这里是一个完整的处理所有错误页面的小集合:

@Controller
public class ErrorCodeController extends BaseController {

    @ExceptionHandler(ApplicationException.class)
    @RequestMapping(value="errorPage400", method=RequestMethod.GET)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public String handleBadRequest(ApplicationException ex,HttpServletResponse response, ModelMap map) { 
        map.addAttribute("http-error-code", HttpStatus.BAD_REQUEST);
        return processErrorCodes(ex,response,map);
    }


    @ExceptionHandler(ApplicationException.class)
    @RequestMapping(value="errorPage401", method=RequestMethod.GET)
    @ResponseStatus(value=HttpStatus.UNAUTHORIZED,reason="Unauthorized Request")
    public String handleUnauthorizedRequest(ApplicationException ex,HttpServletResponse response, ModelMap map) { 
        map.addAttribute("http-error-code", HttpStatus.UNAUTHORIZED);
        return processErrorCodes(ex,response,map);
    }


    @ExceptionHandler(ApplicationException.class)
    @RequestMapping(value="errorPage404", method=RequestMethod.GET)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public String handleNotFoundRequest(ApplicationException ex,HttpServletResponse response, ModelMap map) { 
        map.addAttribute("http-error-code", HttpStatus.NOT_FOUND);
        return processErrorCodes(ex,response,map);
    }


    @ExceptionHandler(ApplicationException.class)
    @RequestMapping(value="errorPage500", method=RequestMethod.GET)
    @ResponseStatus(value=HttpStatus.INTERNAL_SERVER_ERROR,reason="Internal Server Error")
    public String handleInternalServerError(ApplicationException ex,HttpServletResponse response, ModelMap map) { 
        map.addAttribute("http-error-code", HttpStatus.INTERNAL_SERVER_ERROR);
        return processErrorCodes(ex,response,map);
    }

    @ExceptionHandler(ApplicationException.class)
    public void handleApplicationExceptions(Throwable exception, HttpServletResponse response) {

    }

    private String processErrorCodes(ApplicationException ex,HttpServletResponse response, ModelMap map){
        map.addAttribute("class", ClassUtils.getShortName(ex.getClass()));
        map.addAttribute("message", ex.getMessage());
        map.addAttribute("errorMessage", ex.getErrorMessage());
        map.addAttribute("errorCode", ex.getErrorCode());
        map.addAttribute("timestamp", ex.getCurrentDate());
        return "errorPage";
    }


}

基础控制器:

@Controller
@RequestMapping("/")
public class BaseController {

    // Remember to add any exception that you suspect can be thrown in this web application.


@ExceptionHandler({ApplicationException.class,NullPointerException.class})
    public ModelAndView handleException(Throwable exception,HttpServletRequest req) {

        ModelMap model = new ModelMap();
        ApplicationException ex = new ApplicationException();
        String timeStamp = ex.getCurrentDate().toString();
        //String temp = ClassUtils.getShortName(ex.getClass());
        //model.addAttribute("class", ClassUtils.getShortName(ex.getClass()));
        model.addAttribute("timeStamp", timeStamp);
        return new ModelAndView("errorPage", model);
    } 

Web.xml:

<web-app id="WebApp_ID" version="2.5"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <display-name>myApp</display-name>
    <error-page>
        <error-code>400</error-code>
        <location>/errorPage400.xhtml</location>
    </error-page>
    <error-page>
        <error-code>401</error-code>
        <location>/errorPage401.xhtml</location>
    </error-page>
    <error-page>
        <error-code>404</error-code>
        <location>/errorPage404.xhtml</location>
    </error-page>
    <error-page>
        <error-code>500</error-code>
        <location>/errorPage500.xhtml</location>
    </error-page>
    <error-page>
        <exception-type>java.lang.Throwable</exception-type>
        <location>/errorPage.xhtml</location>
    </error-page>

【讨论】:

  • 我使用的是 java Config,而不是 web.xml 我需要发送 json,而不是重定向到错误页面
  • 我们应该从 .. 知道这一点?格式化您的帖子。
【解决方案2】:

我知道这是一个老话题,但我也很挣扎,所以这是我的解决方案,仅适用于 Tomcat。

在您的*DispatcherServletInitializer/WebAppInitializer#onStartup(...) 方法中调用以下方法。

Field appContextInFacade = ApplicationContextFacade.class.getDeclaredField("context");
appContextInFacade.setAccessible(true);
ApplicationContext appContext = (ApplicationContext) appContextInFacade.get(servletContext);
Field appContextInContext = ApplicationContext.class.getDeclaredField("context");
appContextInContext.setAccessible(true);
StandardContext context = (StandardContext) appContextInContext.get(appContext);
ErrorPage defaultErrorPage = new ErrorPage();
defaultErrorPage.setLocation("/myinternalerrorhandlercontroller");
context.addErrorPage(defaultErrorPage); // You may have to use reflection here as well.

然后添加一个能够处理这些错误请求的控制器:

@RequestMapping("/myinternalerrorhandlercontroller")
public ResponseEntity<T> renderErrorPage(HttpServletRequest httpRequest)

您可以使用以下方法提取错误详细信息:

(Integer) httpRequest.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);

重要提示:

  • 你必须处理所有RequestMethods。
  • 您必须处理所有 Content-Types(=> 返回字节或注册一个备用 HttpMessageConverter,无论请求什么,它都可以将您的错误对象转换为 json)。
  • 您的错误页面绝不能抛出异常或无法返回响应。
  • 仅当通常的@ExceptionHandler 或类似机制未被调用或(无法执行)时才会显示错误页面。
  • 不要访问您的应用程序状态,例如用户身份验证,因为您超出了他们的范围,它们可能不可用或包含无效数据。

【讨论】:

    猜你喜欢
    • 2020-11-17
    • 2020-09-13
    • 2022-06-17
    • 1970-01-01
    • 2019-10-13
    • 2015-12-04
    • 2022-01-21
    • 2013-10-17
    • 1970-01-01
    相关资源
    最近更新 更多