权限与认证:HTTP 状态码返回

2021-07-29 16:41:35 浏览数 (1)

系列文章:

权限与认证:JWT

权限与认证:JWT 实践

权限与认证:基于 JWT 的授权实现

一 概述

权限与认证:基于 JWT 的授权实现中提到了登录授权时的token信息拦截和解析,并在验证通过后进行用户信息相关的参数注入。但在真实业务中还会经常遇到这样的需求,授权验证失败,我们希望返回401的HTTP错误码,对应的,可能还有401、302等等其他需求。这里就通过一个示例来进行说明。

二 HTTP常用错误码

这相关的资料百度一搜到处都是,这里就不再重复描述了。不过会提取出鉴权相关的错误码如下:

2.1 401-unauthorized

原因:您的web服务器开启了密码验证,客户端在请求的时候需要填入用户名和密码,只有输入正确的用户名和密码才能正常访问。

解决:输入正确的用户名和密码;关闭web服务器的密码验证功能。

2.2 403-Forbidden

原因:禁止访问,请求是合法的,但是却因为服务器配置规则而拒绝响应客户端请求,此类问题一般为服务器或服务权限配置不当导致。

解决:确保主页文件存在,如index.php或index.html;确保web服务器运行用户和站点的目录权限一致,比如你的nginx运行用户为www,你需要确保你的站点目录的所有者为www。

三 HttpServletResponse中的错误码定义

javax.servlet.http包中的HttpServletResponse是一个接口,继承自ServletResponse。其中定义了从100到505的HTTP错误码:

代码语言:javascript复制
int SC_CONTINUE = 100;
    int SC_SWITCHING_PROTOCOLS = 101;
    int SC_OK = 200;
    int SC_CREATED = 201;
    int SC_ACCEPTED = 202;
    int SC_NON_AUTHORITATIVE_INFORMATION = 203;
    int SC_NO_CONTENT = 204;
    int SC_RESET_CONTENT = 205;
    int SC_PARTIAL_CONTENT = 206;
    int SC_MULTIPLE_CHOICES = 300;
    int SC_MOVED_PERMANENTLY = 301;
    int SC_MOVED_TEMPORARILY = 302;
    int SC_FOUND = 302;
    int SC_SEE_OTHER = 303;
    int SC_NOT_MODIFIED = 304;
    int SC_USE_PROXY = 305;
    int SC_TEMPORARY_REDIRECT = 307;
    int SC_BAD_REQUEST = 400;
    int SC_UNAUTHORIZED = 401;
    int SC_PAYMENT_REQUIRED = 402;
    int SC_FORBIDDEN = 403;
    int SC_NOT_FOUND = 404;
    int SC_METHOD_NOT_ALLOWED = 405;
    int SC_NOT_ACCEPTABLE = 406;
    int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
    int SC_REQUEST_TIMEOUT = 408;
    int SC_CONFLICT = 409;
    int SC_GONE = 410;
    int SC_LENGTH_REQUIRED = 411;
    int SC_PRECONDITION_FAILED = 412;
    int SC_REQUEST_ENTITY_TOO_LARGE = 413;
    int SC_REQUEST_URI_TOO_LONG = 414;
    int SC_UNSUPPORTED_MEDIA_TYPE = 415;
    int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
    int SC_EXPECTATION_FAILED = 417;
    int SC_INTERNAL_SERVER_ERROR = 500;
    int SC_NOT_IMPLEMENTED = 501;
    int SC_BAD_GATEWAY = 502;
    int SC_SERVICE_UNAVAILABLE = 503;
    int SC_GATEWAY_TIMEOUT = 504;
    int SC_HTTP_VERSION_NOT_SUPPORTED = 505;

四 实现示例

改动点在AuthenticationInterceptor.java,在拦截token信息并鉴权时,加上错误token时的返回信息:

代码语言:javascript复制
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
        String token = request.getHeader(TokenUtil.SAFETY_TOKEN_KEY);

        if (!(object instanceof HandlerMethod)) {
            return true;
        }

        if (token == null) {
            return print(request, response);
        }

        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("xxxxxx")).build();
        try {
            jwtVerifier.verify(token);
        } catch (JWTVerificationException e) {
            logger.error("错误的token : "   e.getMessage());
            return print(request, response);
        }

关键就是在print(request, response)方法,内容如下:

代码语言:javascript复制
private boolean print(HttpServletRequest request, HttpServletResponse response) {
    response.setCharacterEncoding("utf-8");
    response.setContentType("application/json;charset=UTF-8");
    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    try (
            OutputStream out = response.getOutputStream();
            PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, "utf-8"))
    ) {
        pw.print("{"errorMessage":"token过期"}");
        pw.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return false;
}
代码语言:javascript复制

其实非常简单。使用OutputStream 打印token消息,并在response中设置status为HttpServletResponse.SC_UNAUTHORIZED即可。简单来说,就这一句是关键。

0 人点赞