写点什么

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

发布于: 52 分钟前
权限与认证:HTTP状态码返回

系列文章:

权限与认证: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 错误码:


    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 时的返回信息:


    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)方法,内容如下:

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;}
复制代码

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

发布于: 52 分钟前阅读数: 2
用户头像

磨炼中成长,痛苦中前行 2017.10.22 加入

微信公众号【程序员架构进阶】。多年项目实践,架构设计经验。曲折中向前,分享经验和教训

评论

发布
暂无评论
权限与认证:HTTP状态码返回