精华内容
下载资源
问答
  • 在单点登录情况,客户端应用接入CAS服务端后,特别是外网环境会经常出现401的问题,要么直接跳转到登录页面,要么就直接响应401。注意此时CAS服务端的TGT并没有超时。只能排查后端的日志信息,开启debug模式看到了...

    单点登录情况下的现象

    在单点登录情况,客户端应用接入CAS服务端后,特别是外网环境会经常出现401的问题,要么直接跳转到登录页面,要么就直接响应401。注意此时CAS服务端的TGT并没有超时。只能排查后端的日志信息,开启debug模式看到了如下的后端异常信息:

     [org.jasig.cas.web.support.TGCCookieRetrievingCookieGenerator] - Invalid cookie. Required remote address does not match XXX.XXX.XXX.XX
    java.lang.IllegalStateException: Invalid cookie. Required remote address does not match XXX.XXX.XXX.XX
    

    问题应该很明确,就是产生TGT时候,所使用的客户端IP和再次请求进来时所使用的客户端IP地址不一致导致无法通过校验。客户端浏览器就算有TGC的cookie存在,因为校验报错后也无法再走后续流程,直接到登录页面或者401。

    CAS获取cookie中的TGC实现类

    有了上面的错误信息,我们可以知道CAS服务端中获取到客户端浏览器中的tgc都是通过TGCCookieRetrievingCookieGenerator来实现的。我们来一起解析一下这个包中所有类相关的功能。(注意本系列所使用的CAS服务端的版本代码)。
    类所在的包名为cas-server-webapp-cookie,其中的package中有如下的Java类。

    org.jasig.cas.web.support.CookieRetrievingCookieGenerator
    org.jasig.cas.web.support.CookieValueManager
    org.jasig.cas.web.support.DefaultCasCookieValueManager
    org.jasig.cas.web.support.NoOpCookieValueManager
    org.jasig.cas.web.support.TGCCookieRetrievingCookieGenerator

    主要看TGCCookieRetrievingCookieGenerator和DefaultCasCookieValueManager这两个类中是如何处理的。
    CAS服务端的代码中获取cookie时,一般使用的都是默认CookieRetrievingCookieGenerator这个类,然后注入不同的实现

     /** CookieGenerator for the TicketGrantingTickets. */
        @NotNull
        private CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator;
    /** 注入具体的实现*/
      @Autowired
        public void setTicketGrantingTicketCookieGenerator(
            @Qualifier("ticketGrantingTicketCookieGenerator")
            final CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator) {
            this.ticketGrantingTicketCookieGenerator = ticketGrantingTicketCookieGenerator;
        }
    
    

    解析获取tgc实现类中如何处理客户端信息

    知道TGC获取的具体的代码为TGCCookieRetrievingCookieGenerator这个类,进行一下分析

    @Component("ticketGrantingTicketCookieGenerator")
    public class TGCCookieRetrievingCookieGenerator extends CookieRetrievingCookieGenerator {
    
        /**
         * Instantiates a new TGC cookie retrieving cookie generator.
         *
         * @param casCookieValueManager the cas cookie value manager
         * 注意构造函数中使用的cookie管理类,这是我们需要重点分析,也是主要用于存取cookie的关键类。
         */
        @Autowired
        public TGCCookieRetrievingCookieGenerator(@Qualifier("defaultCookieValueManager")
            final CookieValueManager casCookieValueManager) {
            super(casCookieValueManager);
        }
    	//定义cookie名称
        @Override
        @Autowired
        public void setCookieName(@Value("${tgc.name:TGC}")
                                      final String cookieName) {
            super.setCookieName(cookieName);
        }
    	//定义cookie中的路径
        @Override
        @Autowired
        public void setCookiePath(@Value("${tgc.path:}")
                                      final String cookiePath) {
            super.setCookiePath(cookiePath);
        }
    	//定义cookie的生命周期
        @Override
        @Autowired
        public void setCookieMaxAge(@Value("${tgc.maxAge:-1}")
                                        final Integer cookieMaxAge) {
            super.setCookieMaxAge(cookieMaxAge);
        }
    	//定义cookie是否安全
        @Override
        @Autowired
        public void setCookieSecure(@Value("${tgc.secure:true}")
                                        final boolean cookieSecure) {
            super.setCookieSecure(cookieSecure);
        }
    	//定义记住cookie的最大时间
        @Override
        @Autowired
        public void setRememberMeMaxAge(@Value("${tgc.remember.me.maxAge:1209600}")
                                    final int max) {
            super.setRememberMeMaxAge(max);
        }
    

    通过TGCCookieRetrievingCookieGenerator的分析我们知道重点还是在cookie的管理类上,那么继续分析一下管理类中是如何实现的。

      @Autowired
        public DefaultCasCookieValueManager(@Qualifier("defaultCookieCipherExecutor")
                                                final CipherExecutor<String, String> cipherExecutor) {
            this.cipherExecutor = cipherExecutor;
            LOGGER.debug("Using cipher [{} to encrypt and decode the cookie",
                    this.cipherExecutor.getClass());
        }
    
        @Override
        public String buildCookieValue(final String givenCookieValue, final HttpServletRequest request) {
            final StringBuilder builder = new StringBuilder(givenCookieValue);
    
            final String remoteAddr = request.getRemoteAddr();
            if (StringUtils.isBlank(remoteAddr)) {
                throw new IllegalStateException("Request does not specify a remote address");
            }
            //加入用户客户端的IP地址
            builder.append(COOKIE_FIELD_SEPARATOR);
            builder.append(remoteAddr);
    
            final String userAgent = request.getHeader("user-agent");
            if (StringUtils.isBlank(userAgent)) {
                throw new IllegalStateException("Request does not specify a user-agent");
            }
            //加入用户发起请求时的header头中的user-agent信息
            builder.append(COOKIE_FIELD_SEPARATOR);
            builder.append(userAgent);
    
            final String res = builder.toString();
            LOGGER.debug("Encoding cookie value [{}]", res);
            //对数据进行加密
            return this.cipherExecutor.encode(res);
        }
    
        @Override
        public String obtainCookieValue(final Cookie cookie, final HttpServletRequest request) {
        //解密cookie值
            final String cookieValue = this.cipherExecutor.decode(cookie.getValue());
            LOGGER.debug("Decoded cookie value is [{}]", cookieValue);
            if (StringUtils.isBlank(cookieValue)) {
                LOGGER.debug("Retrieved decoded cookie value is blank. Failed to decode cookie [{}]", cookie.getName());
                return null;
            }
    		//根据分割符分割cookie值
            final String[] cookieParts = cookieValue.split(String.valueOf(COOKIE_FIELD_SEPARATOR));
            if (cookieParts.length != COOKIE_FIELDS_LENGTH) {
                throw new IllegalStateException("Invalid cookie. Required fields are missing");
            }
            final String value = cookieParts[0];
            final String remoteAddr = cookieParts[1];
            final String userAgent = cookieParts[2];
    
            if (StringUtils.isBlank(value) || StringUtils.isBlank(remoteAddr)
                    || StringUtils.isBlank(userAgent)) {
                throw new IllegalStateException("Invalid cookie. Required fields are empty");
            }
    		//校验tgc中产生的客户端IP地址和再次请求的IP地址是否一致
            if (!remoteAddr.equals(request.getRemoteAddr())) {
                throw new IllegalStateException("Invalid cookie. Required remote address does not match "
                        + request.getRemoteAddr());
            }
    		//校验tgc中产生的用户请求user-agent和再次发起请求的user-agent的值是否一致
            if (!userAgent.equals(request.getHeader("user-agent"))) {
                throw new IllegalStateException("Invalid cookie. Required user-agent does not match "
                        + request.getHeader("user-agent"));
            }
            return value;
        }
    

    构造函数中使用的是对于写到客户端中的tgc的加密方式,不在这里展开,有兴趣的可自己深入。
    看一下buildCookieValue这个方法,我们对响应客户端的cookie中写入了一些什么属性。

    builder.append(remoteAddr);用户客户端的IP地址
    builder.append(userAgent);用户请求header头中的user-agent属性值

    写入这两个信息到tgc的cookie中有什么用呢?看一下obtainCookieValue方法我们就一目了然了。

    比较客户端IP地址是否一致
    if (!remoteAddr.equals(request.getRemoteAddr())) {
    throw new IllegalStateException("Invalid cookie. Required remote address does not match "
    + request.getRemoteAddr());
    }

    比较客户端请求头中user-agent的值是否一致
    if (!userAgent.equals(request.getHeader(“user-agent”))) {
    throw new IllegalStateException("Invalid cookie. Required user-agent does not match "
    + request.getHeader(“user-agent”));
    }

    总结

    通过解读代码我们可知,在获取TGC的时候是要进行安全性校验的:客户端IP地址校验和客户端请求头user-agent的值校验。
    1、如果在IP地址不固定,甚至是会漂移的情况下,那么在单点登录多系统集成甚至是单系统接入session超时后,都可以发生让你重新登录系统的情况。(简单测试:有限和无线切换之后,保证IP不一样,等待客户端会话超时,但是CAS服务端TGT未超时情况下,这时你就要重新登录。)
    2、如果你的请求header头中改变了user-agent的值,那么很不幸,就是你tgt在未超时的情况下,客户端系统在单点登录下也还是要重新登录。

    展开全文
  • 对于存在的网页,但用户没有足够特权(他们没有登录或不属于适当的用户组)的网页,可以提供什么适当的HTTP响应401 Unauthorized ? 403 Forbidden吗?

    对于存在的网页,但用户没有足够特权(他们没有登录或不属于适当的用户组)的网页,可以提供什么适当的HTTP响应?

    401 Unauthorized
    403 Forbidden吗?
    还有吗

    到目前为止,我对两者的区别还不清楚。 每种使用情况适合哪些用例?


    #1楼

    他们没有登录或不属于正确的用户组

    您陈述了两种不同的情况; 每种情况应有不同的响应:

    1. 如果根本没有登录,则应返回401未经授权
    2. 如果他们已登录但不属于正确的用户组,则应返回403 Forbidden

    根据对此答案收到的评论,在RFC上进行说明:

    如果用户未登录,则他们未经身份验证,其HTTP等效项是401,并且在RFC中被误称为“未经授权”。 如第10.4.2节所述,针对401未经授权

    “该请求需要用户验证 。”

    如果您未经身份验证,则401是正确的响应。 但是,如果您未经授权,则从语义上正确的意义上来说,403是正确的响应。


    #2楼

    缺少其他答案的是,必须理解,在RFC 2616上下文中的身份验证和授权仅引用RFC 2617的HTTP身份验证协议。HTTP状态码不支持通过RFC2617之外的方案进行身份验证,因此不考虑在决定使用401还是403时。

    简明扼要

    未经授权表示客户端未通过RFC2617认证,服务器正在启动认证过程。 “禁止”表示客户端已通过RFC2617认证并且没有授权,或者服务器不支持所请求资源的RFC2617。

    这意味着,如果您有自己的自备登录过程并且从不使用HTTP身份验证,则403始终是正确的响应,并且永远不应该使用401。

    详细和深入

    从RFC2616

    10.4.2 401未经授权

    该请求需要用户认证。 响应必须包括一个WWW-Authenticate头域(第14.47节),该头域包含适用于所请求资源的质询。 客户可以用合适的授权头域(第14.8节)重复请求。

    10.4.4 403禁止服务器理解了请求,但拒绝执行。 授权将无济于事,不应重复该请求。

    首先要记住的是,本文档中的“身份验证”和“授权”是专门指RFC 2617中的HTTP身份验证协议。它们不涉及您可能创建的任何自带身份验证协议使用登录页面等。我将使用“登录”来指通过RFC2617以外的方法进行身份验证和授权

    因此,真正的区别不在于问题是什么,甚至不是解决方案。 区别在于服务器希望客户端接下来执行的操作。

    401指示无法提供资源,但是服务器正在请求客户端通过HTTP身份验证登录,并已发送了回复标头以启动该过程。 可能有一些授权将允许访问该资源,也许没有,但是让我们尝试一下看看会发生什么。

    403表示无法提供资源,对于当前用户,没有办法通过RFC2617解决此问题,也没有尝试的意义。 这可能是因为已知没有足够的身份验证级别(例如,由于IP黑名单),但是可能是因为用户已经通过身份验证并且没有权限。 RFC2617模型是一个单用户单凭证,因此可以忽略用户可能拥有第二组可以授权的凭证的情况。 它既不暗示也不暗示某种登录页面或其他非RFC2617身份验证协议可能会或可能不会有所帮助-这超出了RFC2616标准和定义。


    编辑: RFC2616已过时,请参阅RFC7231RFC7235


    #3楼

    假设HTTP认证 (WWW身份验证授权头) 在使用中 ,如果认证作为另一个用户将授予访问所请求的资源,那么401未授权应返回。

    403 Forbidden用于禁止所有人访问资源或限制访问给定网络或仅通过SSL允许访问资源,只要与HTTP身份验证无关即可。

    如果未使用HTTP身份验证,并且按当今的标准为基于cookie的身份验证服务提供服务,则应返回403或404。

    关于401,这来自RFC 7235(超文本传输​​协议(HTTP / 1.1):身份验证):

    3.1。 401未经授权

    401(未经授权)状态码表示该请求尚未应用,因为它缺少针对目标资源的有效身份验证凭据。 源服务器必须发送一个包含至少一个适用于目标资源的质询的WWW-Authenticate头域(第4.4节)。 如果请求包括认证证书,则401响应指示已拒绝那些证书的授权 。 客户端可以用一个新的或替换的Authorization头域(4.1节)重复请求。 如果401响应包含与先前响应相同的质询,并且用户代理已经尝试了至少一次身份验证,则用户代理应该向用户呈现随附的表示,因为它通常包含相关的诊断信息。

    403(和404)的语义已随时间而改变。 这是从1999(RFC 2616)开始的:

    10.4.4 403禁止

    服务器理解了该请求,但拒绝执行该请求。
    授权将无济于事 ,不应重复该请求。
    如果请求方法不是HEAD并且服务器希望执行
    公开为什么请求没有得到满足,应该在实体中描述拒绝的原因。 如果服务器不希望将此信息提供给客户端,则状态码为404
    (未找到)可以代替使用。

    2014年,RFC 7231(超文本传输​​协议(HTTP / 1.1):语义和内容)更改了403的含义:

    6.5.3。 403禁止

    403(禁止)状态码表示服务器理解了请求,但拒绝授权。 希望公开为什么禁止请求的服务器可以在响应有效负载(如果有)中描述该原因。

    如果请求中提供了身份验证凭据,则
    服务器认为它们不足以授予访问权限。 客户端
    不应自动将相同的请求重复
    证书。 客户端可以用新的或不同的证书重复请求。 但是,出于某些原因,请求可能被禁止
    与凭据无关。

    希望“隐藏”当前存在的原始服务器
    禁止的目标资源可能会以状态码回应
    404(未找到)。

    因此,403(或404)现在可能意味着任何事情。 提供新的凭据可能会有所帮助...或可能没有帮助。

    我相信这已经改变的原因是RFC 2616假定在当今的Web应用程序在实践中使用例如表单和cookie构建自定义身份验证方案时将使用HTTP身份验证。


    #4楼

    这个问题是在不久前提出的,但是人们的想法在不断发展。

    该草案(由Fielding和Reschke撰写)的6.5.3节为状态代码403赋予了与RFC 2616中所记录的含义稍有不同的含义。

    它反映了许多流行的Web服务器和框架采用的身份验证和授权方案中发生的情况。

    我强调了我认为最突出的一点。

    6.5.3。 403禁止

    403(禁止)状态码表示服务器理解了请求,但拒绝授权。 希望公开为什么禁止请求的服务器可以在响应有效负载(如果有)中描述该原因。

    如果请求中提供了身份验证凭据,则服务器认为它们不足以授予访问权限。 客户端不应使用相同的凭证重复请求。 客户可以用新的或不同的证书重复请求。 但是,出于与凭据无关的原因,可能会禁止请求。

    希望“隐藏”当前存在的禁止目标资源的原始服务器可以使用状态代码404(未找到)进行响应。

    无论使用哪种约定,重要的是要在整个站点/ API之间提供统一性。


    #5楼

    在401 vs 403的情况下,已经回答了很多次。 这本质上是“ HTTP请求环境”辩论,而不是“应用程序”辩论。

    关于“自己动手登录”问题(应用程序)似乎存在一个问题。

    在这种情况下,除非您使用HTTP身份验证而不是登录页面(与设置HTTP身份验证无关),否则仅不登录就不足以发送401或403。 听起来您可能正在寻找“ 201 Created”(创建201),其中存在“您自己登录”的滚动屏幕(而不是请求的资源),以供应用程序级访问文件。 这说:

    “我听说过,它在这里,但请尝试一下(不允许您看到它)”


    #6楼

    这是一个比较老的问题,但是从未真正提出过的一种选择是返回404。从安全角度来看,投票率最高的答案有潜在的信息泄漏漏洞 。 例如,假设所讨论的安全网页是系统管理员页面,或更常见的是,是用户无法访问的系统中的记录。 理想情况下,您甚至不希望恶意用户知道那里有一个页面/记录,更不用说他们没有访问权限了。 当我构建类似这样的东西时,我将尝试在内部日志中记录未认证/未授权的请求,但返回404。

    OWASP提供了有关攻击者如何在攻击过程中使用此类信息的更多信息


    #7楼

    Resource exists ? (if private it is often checked AFTER auth check)
        |       |
     NO |       | YES
        v       v
       404      Is logged-in ? (authenticated, aka has session)
       or         |              |
       401     NO |              | YES
       403        |              |
                  v              v
                  401            Can access resource ? (permission, authorized) ?
             (404 no reveal)      |            |
                 or 301        NO |            | YES
                 redirect         |            |
                 to login         v            v
                                  403          OK 200, 301, ...
                          (or 404: no reveal)

    通常按以下顺序进行检查:

    • 401(如果未登录或会话已过期)
    • 403,如果用户无权访问资源(文件,json,...)
    • 404(如果资源不存在(或不愿透露任何内容))

    UNAUTHORIZED :状态码(401),指示请求需要身份验证 ,通常这意味着用户需要登录(会话)。 服务器未知的用户/代理。 可以重复使用其他凭据。 注意:这令人困惑,因为它应该被命名为“未经身份验证”而不是“未经授权”。 如果会话过期,登录后也可能发生这种情况。 特殊情况:可以代替404使用,以避免显示资源的存在或不存在(信用@gingerCodeNinja)

    禁止 :状态代码(403)指示服务器理解了该请求,但拒绝执行该请求。 服务器已知的用户/代理,但凭据不足 。 除非更改凭据,否则重复请求将不起作用,这在很短的时间内是非常不可能的。 特殊情况:可以代替404使用,以避免显示资源的存在或不存在(信用@gingerCodeNinja)

    未找到 :状态代码(404),指示请求的资源不可用。 用户/代理已知,但服务器不会显示任何有关资源的信息,就像不存在该信息一样。 重复将不起作用。 这是404的一种特殊用法(例如github)。


    #8楼

    TL; DR

    • 401:与身份验证有关的拒绝
    • 403:与身份验证无关的拒绝

    实际例子

    如果apache 需要验证 (通过.htaccess ),并且您单击Cancel ,它将以401 Authorization Required响应。

    如果nginx找到文件,但是没有读取/访问该文件的访问权限 (用户/组),它将以403 Forbidden响应

    RFC(2616第10节)

    401未经授权(10.4.2)

    含义1: 需要认证

    该请求需要用户认证。 ...

    含义2: 认证不足

    ...如果请求已包含授权凭证,则401响应指示已拒绝这些凭证的授权。 ...

    403禁止(10.4.4)

    含义: 与身份验证无关

    ...授权将无济于事...

    更多细节:

    • 服务器理解了该请求,但拒绝执行该请求。

    • 它应该描述实体拒绝的原因

    • 可以使用状态代码404(未找到)

      (如果服务器希望从客户端保留此信息)


    #9楼

    根据RFC 2616 (HTTP / 1.1),在以下情况下发送403:

    服务器理解了该请求,但拒绝执行该请求。 授权将无济于事,不应重复该请求。 如果请求方法不是HEAD,并且服务器希望公开为什么未满足请求,则应在实体中描述拒绝原因。 如果服务器不希望将此信息提供给客户端,则可以使用状态代码404(未找到)代替

    换句话说,如果客户端可以通过身份验证访问资源,则应发送401。


    #10楼

    参见RFC2616

    401未经授权:

    如果请求已包含授权凭证,则401响应指示已拒绝这些凭证的授权。

    403禁止:

    服务器理解了该请求,但拒绝执行该请求。

    更新资料

    从您的用例来看,似乎用户未通过身份验证。 我会返回401。


    编辑: RFC2616已过时,请参阅RFC7231RFC7235


    #11楼

    在我看来,这比这里任何地方都简单,因此:

    401:您需要HTTP基本身份验证才能看到此信息。

    403:您看不到这一点,HTTP基本身份验证也无济于事。

    如果用户只需要使用您网站的标准HTML登录表单登录,则401不适用,因为它特定于HTTP基本身份验证。

    我不建议使用403拒绝访问/includes类的东西,因为就网络而言,这些资源根本不存在,因此应该为404。

    这将403保留为“您需要登录”。

    换句话说,403的意思是“此资源需要除HTTP基本身份验证以外的某种形式的身份验证”。

    https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2


    #12楼

    我认为重要的是要考虑到,对于浏览器,401会启动一个身份验证对话框,供用户输入新的凭据,而403则不会。 浏览器认为,如果返回401,则用户应重新进行身份验证。 因此401代表无效身份验证,而403代表缺少权限。

    在这种逻辑下,在某些情况下会从身份验证或授权返回错误,并用粗体显示重要的短语。

    • 资源需要身份验证,但未指定 凭据

    401 :客户端应指定凭据。

    • 指定的凭据格式无效

    400 :既不是401也不是403,因为语法错误应始终返回400。

    • 指定的凭据引用了不存在用户

    401 :客户端应指定有效的凭据。

    • 指定的凭据 无效,但指定了有效用户(如果不需要指定用户,则不要指定用户)。

    401 :同样,客户端应指定有效的凭证。

    • 指定的凭据过期

    401 :这实际上与通常具有无效凭据的相同,因此客户端应指定有效凭据。

    • 指定的凭据完全有效,但不能满足特定资源的需求 ,尽管具有更多权限的凭据可能会出现。

    403 :指定有效凭据不会授予对资源的访问权限,因为当前凭据已经有效,但仅没有权限。

    • 无论凭证如何,都无法访问特定资源

    403 :这与凭据无关,因此指定有效的凭据无济于事。

    • 指定的凭据是完全有效的,但在特定的客户端使用阻止他们。

    403 :如果客户端被阻止,则指定新凭据将无济于事。


    #13楼

    考虑到有关此问题的最新RFC( 72317235 ),用例似乎很清楚(添加了斜体):

    • 401用于未认证 (“缺少有效认证”); 即“我不知道你是谁,或者我不相信你是你所说的你。”

    401未经授权

    401(未经授权)状态码表示该请求尚未应用,因为它缺少针对目标资源的有效身份验证凭据。 产生401响应的服务器必须发送WWW-Authenticate头域(4.1节),该域包含至少一个适用于目标资源的质询。

    如果请求包括身份验证凭据,则401响应指示已拒绝这些凭据的授权。 用户代理可以用一个新的或替换的Authorization头域(4.2节)重复请求。 如果401响应包含与先前响应相同的质询,并且用户代理已经尝试了至少一次身份验证,则用户代理应该向用户呈现随附的表示,因为它通常包含相关的诊断信息。

    • 403用于未授权 (“拒绝授权”); 即“我知道您是谁,但您无权访问此资源。”

    403禁止

    403(禁止)状态码表示服务器理解了请求,但拒绝授权 。 希望公开为什么禁止请求的服务器可以在响应有效负载(如果有)中描述该原因。

    如果请求中提供了身份验证凭据,则服务器认为它们不足以授予访问权限。 客户端不应该自动使用相同的凭据重复请求。 客户端可以用新的或不同的证书重复请求。 但是,出于与凭据无关的原因,可能会禁止请求。

    希望“隐藏”当前存在的禁止目标资源的原始服务器可以使用状态代码404(未找到)进行响应。


    #14楼

    401 :我不知道你是谁。 这是身份验证错误。 403 :我知道你是谁 但是您没有访问此资源的权限。 这是授权错误。


    #15楼

    这些含义是:

    401 :用户未(正确)经过身份验证,资源/页面需要身份验证

    403 :用户已通过身份验证,但其角色或权限不允许访问请求的资源,例如,用户不是管理员,而请求的页面是针对管理员的


    #16楼

    Daniel Irvine的明确解释:

    401 Unauthorized出现问题,身份验证错误的HTTP状态代码。 就是这样:它用于身份验证,而不是授权。 收到401响应的服务器会告诉您:“您没有通过身份验证-根本没有经过身份验证或身份验证不正确-但请重新进行身份验证并重试。”为了帮助您,它将始终包含一个WWW-Authenticate标头,该标头描述了如何验证。

    这是通常由您的Web服务器而不是Web应用程序返回的响应。

    这也是非常临时的。 服务器要求您重试。

    因此,对于授权,我使用403禁止响应。 它是永久的,与我的应用程序逻辑相关,并且比401更具体。

    服务器收到403响应,告诉您:“很抱歉。 我知道您是谁-我相信您说的是谁-但您只是没有访问此资源的权限。 也许如果您很好地询问系统管理员,您将获得许可。 但是请不要再困扰我,直到您的困境改变为止。”

    总而言之,当用户经过身份验证但无权对给定资源执行请求时,应使用401未经授权的响应来进行丢失或错误的身份验证,然后使用403禁止响应。

    另一种不错的图片格式 ,说明应如何使用http状态代码。

    在此处输入图片说明

    展开全文
  • 关于401错误 401错误场景 1. 用户未登录,代码报401,应该回到登录页 2. 登录用户的token过期 : 怎样理解token过期? . 就是登录成功了以后,后端会返回一个token值,这个值在后续请求时带上(就像是开门钥匙), ...

    关于401错误

     

    401错误场景

    1. 用户未登录,代码报401,应该回到登录页

    2. 登录用户的token过期 :

    怎样理解token过期?

    . 就是登录成功了以后,后端会返回一个token值,这个值在后续请求时带上(就像是开门钥匙),

    但是,这个值一般会有有效期(具体是多长,是由后端决定)token过期是为了安全起见

     

    refresh_token

    说明 : 当用户登陆成功之后,返回的token中有两个值

    图示说明:

    作用:


    响应拦截器

     

    说明

    响应拦截器可以解决401错误

     

    响应拦截器的功能

    所有从后端回来的响应都会集中进入响应拦截器中,如果发生401错误就可以解决

     

    图示说明

     

    代码演示

    import router from '../router/auth.js'
    
    
    // 响应拦截器
    request.interceptors.response.use(function (response) {
      console.log('响应拦截器', response)
      return response
    }, async function (error) {
      // 如果发生了错误,判断是否是401
      console.dir(error)
      if (error.response.status === 401) {
        // 出现401就在这里面 开始处理 ---
        console.log('响应拦截器-错误-401')
        const refreshToken = store.state.tokenInfo.refresh_token
        // if (有refresh_token) {       ---- 有refresh_token
        if (refreshToken) {
          // 1. 请求新token
          try {
            const res = await axios({
              url: 'http://localhost:8000/v1_0/authorizations',
              method: 'PUT',
              headers: {
                Authorization: `Bearer ${refreshToken}`
              }
            })
            console.log('请求新token', res.data.data.token)
            // 2. 保存到vuex
            store.commit('mSetToken', {   // mSetToken是前面定义的mutations名字
              refresh_token: refreshToken,
              token: res.data.data.token
            })
            // 3. 重发请求
            //    request是上面创建的axios的实例,它会自动从vuex取出token带上
            return request(error.config)
          } catch (error) {
            // 1. 清除token
            store.commit('mSetToken', {})  
            // 2. 去到登录页(如果有token值,就不能到login)
            const backtoUrl = encodeURIComponent(router.currentRoute.fullPath)
            router.push('/login?backto=' + backtoUrl)  
            return Promise.reject(error) 
          }
        } else {
           // 如果没有refresh_token的时候   ----没有refresh_token
          // 1.去到登录页
          // 2.清除token
          store.commit('mSetToken', {})
          const backtoUrl = encodeURIComponent(router.currentRoute.fullPath)  // 回到原来跳过来的的页面,不加?后面的一串就会到首页
          router.push('/login?backto=' + backtoUrl)
          return Promise.reject(error)  // 返回错误信息
        }
      } else {
        return Promise.reject(error)
      }
    })
    

    原理

     

    它的执行顺序是: 请求接口 --> 发生401报错 --> 判断是否有refresh_token -->如果有就用fresh_token请求新的token --> 后台成功返回一个新的token给我们 --> 更新vuex --> 然后重新发送请求 --> 带上新的token请求数据

    如果是异常情况: 就是没有fresh_token的情况

    展开全文
  • 在默认创建的Asp.Net MVC项目中(这里使用VS2013),需要手动返回一个401响应码给浏览器。我们的代码可能是下面这样子的。 1 public ActionResult UnauthorizedAccess() 2 { 3 return new ...
    需求:
        在默认创建的 Asp.Net MVC项目中(这里使用VS2013),需要手动返回一个401响应码给浏览器。我们的代码可能是下面这样子的。
     
    1. 1         public ActionResult UnauthorizedAccess()
      2         {
      3             return new HttpStatusCodeResult((int)HttpStatusCode.Unauthorized);
      4         }
     
    实际的效果却和预期的不太一样,如果我们是通过地址栏直接访问这个Action,可以看到请求被重定向到登录页面了
     
     
    如果通过Ajax的方式进行访问,可以看到直接返回了一个200的响应码
     
    因为当前创建的MVC项目默认使用的是一个叫CookieAuthentication的OWIN中间件来实现身份认证的功能的,该中间件中会将401响应码进行特殊处理,所以导致我们无法手动返回401响应码。
     
    Startup类中的代码: 
    1.  1             // 使应用程序可以使用 Cookie 来存储已登录用户的信息
       2             // 并使用 Cookie 来临时存储有关使用第三方登录提供程序登录的用户的信息
       3             // 配置登录 Cookie
       4             app.UseCookieAuthentication(new CookieAuthenticationOptions
       5             {
       6                 AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
       7                 LoginPath = new PathString("/Account/Login"),
       8                 Provider = new CookieAuthenticationProvider
       9                 {
      10                     // 当用户登录时使应用程序可以验证安全戳。
      11                     // 这是一项安全功能,当你更改密码或者向帐户添加外部登录名时,将使用此功能。
      12                     OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
      13                         validateInterval: TimeSpan.FromMinutes(30),
      14                         regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
      15                 }
      16             });
     
     
     
    所以如果你使用上述的中间件 (使用其他的身份认证的组件也可能会存在重写401响应码的行为) ,那么就无法手动返回401响应码
     
    如果需要手动返回401响应码,那么就需要在Asp.Net的生命周期中对相应做一些修改,查阅MSDN的资料可以看到 PreSendRequestHeaders事件中比较适合做这个操作。
     
     
    在Global中我们添加如下方法,在 PreSendRequestHeaders事件中插入我们自己的代码,将响应码设置为我们预期想要的值
    1.  1         public void Application_PreSendRequestHeaders(object sender, EventArgs e)
       2         {
       3             //处理401响应被多个框架重写的问题
       4             var values = Response.Headers.GetValues(ForceHttpStatusCodeResult.ForceHttpUnauthorizedHeaderName);
       5             if (values != null && values.Contains(ForceHttpStatusCodeResult.ForceHttpUnauthorizedHeaderValue))
       6             {
       7                 Response.ClearHeaders();
       8                 Response.StatusCode = (int)HttpStatusCode.Unauthorized;
       9             }
      10         }
     
     
    由于请求到这里的时候,响应码已经被重写,所以我们通过一个自定义的请求头来标识当前请求是一个要被手动发送给客户端的401响应
     
     1     /// <summary>
     2     /// 强制返回指定的响应码
     3     /// 401响应码会被MVC框架和OWIN授权认证的中间件给重写
     4     /// </summary>
     5     public class ForceHttpStatusCodeResult : HttpStatusCodeResult
     6     {
     7 
     8         public const string ForceHttpUnauthorizedHeaderName = "ForceHttpUnauthorizedHeader";
     9         public const string ForceHttpUnauthorizedHeaderValue = "true";
    10 
    11         public ForceHttpStatusCodeResult(int state)
    12             : this(state, "")
    13         { }
    14 
    15         public ForceHttpStatusCodeResult(int state, string statusDescription)
    16             : base(state, statusDescription)
    17         {
    18             if (state == (int)HttpStatusCode.Unauthorized)
    19             {
    20                 SetForceHttpUnauthorizedHeader();
    21             }
    22         }
    23 
    24 
    25         private void SetForceHttpUnauthorizedHeader()
    26         {
    27             System.Web.HttpContext.Current.Response.AddHeader(ForceHttpUnauthorizedHeaderName, ForceHttpUnauthorizedHeaderValue);
    28         }
    29     }

     

     
     
    此时我们在Action中就可以返回我们需要的任意响应码了
    1. 1         public ActionResult UnauthorizedAccess()
      2         {
      3             return new ForceHttpStatusCodeResult((int)HttpStatusCode.Unauthorized);
      4         }
     
    Ajax请求结果:
     
     
     
    下载:
        示例代码
     
     
    参考资料:
     
     
     

    转载于:https://www.cnblogs.com/mstmdev/p/5110181.html

    展开全文
  • nginx配置cros跨域以及遇到401、500响应的问题 这是我Nginx的server配置: server { listen 80; server_name DataAnalysis; location / { if ($request_method = 'OPTIONS'){ add_header 'Acce...
  • 响应状态码403We've covered the 403 (Forbidden) HTTP Error code in some detail before, but it also has a near identical sibling. 前面我们已经详细介绍了403(禁止)HTTP错误代码,但是它也具有几乎相同的兄弟...
  • 用户骂骂咧咧的删除了网页 (2) 所以啊 这时候refresh_token的作用来了,它的作用呢也可以作为用户的令牌,token失效后,我们可以通过refresh_token去重新获取token 当然这些操作都是报了401错误在响应拦截器里操作...
  • 收到服务器401响应的处理(HTTP或SIP)

    千次阅读 2016-12-08 17:24:37
    这个401响应里面,带了一个验证信息的HEADER, 很明显,这是需要我们发信息去验证,那么,发什么过去呢,问题就来了. 之前并未了解过这一部分的内容, 于是上网查了不少资料. 从HEADER的内容可以看到:Digest ...
  • 然后在发布的时候就出问题了,报401错误[响应状态代码不指示成功: 401 (Unauthorized)。] 原因是添加webservice的时候自动添加的几个程序集,如下 发布提示错误截图如下 解决办法 在项目目录中创建一个包含...
  • 响应,由服务端返回给客户端,可以分为三部分:响应状态码(Response Status Code)、响应头(Response Headers)、响应体(Response Body)。 1、响应状态码 ​ 响应状态码表示服务器的响应状态。在爬虫中,我们可以根据...
  • HTTP响应代码

    千次阅读 2014-05-13 00:29:20
    HTTP响应代码的详细列表,记录在这里以备参考。
  • HTTP 响应代码全集

    千次阅读 多人点赞 2019-10-15 15:01:20
    响应分为五类:信息响应(100–199),成功响应(200–299),重定向(300–399),客户端错误(400–499)和服务器错误(500–599)。状态代码由section 10 of RFC 2616定义 信息响应 100 Continue 这个临时响应表明,...
  • 浏览器向服务器发出请求,服务器处理可能是成功、可能是失败、可能没有权限访问等原因。服务器会通过相应吗来告诉浏览器处理结果。 “200” :OK 301 : move permanently 永久转移 ...401 : unaut
  • 应急响应—常见应急响应处置思路

    千次阅读 多人点赞 2019-12-03 10:19:29
    下图是常见应急响应处置思路的思维导图 下面将对 "常见应急响应处置思路" 进行详细的讲解 一、操作系统后门排查 排查目标:找出后门程序在哪里,找到后门是怎么启动的,尽可能发现后门修改了系统的那些地方。 ...
  • http响应

    千次阅读 2012-07-14 16:25:48
    正如你所见,在响应中唯一真正的区别在于第一行中用状态信息代替了请求信息。状态行(status line)通过提供一个状态码来说明所请求的资源情况。以下就是一个HTTP响应的例子: HTTP/1.1 200 OK Date: Sat, 31 Dec ...
  • jquery ajax是个很常用接口,而在请求时候,可能存在响应401的情况(身份认证过期或未登录),比较容易出现在混合应用上,如何进行身份认证,重发失败请求,还是值得注意的。 ajax请求有两种方式 1. 回调 最常写的...
  • http响应中常见的几种响应代码

    千次阅读 2018-12-28 00:41:00
    Status Code:200表示响应成功,很常见的一个状态 2.300响应代码 Status Code:301 表示客户端跳转,永久性跳转,一般在servlet中使用如下代码 response.setStatus(301); response.setHeader("Location&...
  • http响应代码解释

    2015-10-10 11:19:41
    200:成功响应 302:找到,但是请求的资源在另外一个不同的url中。 400:错误请求。这个请求不能被服务器所理解,客户端必须修改请求。 401:未认证,这个请求需要用户认证。 404:未找到。服务器没有找到任何和...
  • HTTP 响应的格式及状态码

    千次阅读 2019-02-13 22:11:16
    HTTP响应 服务器收到了客户端发来的HTTP请求后,根据HTTP请求中的动作要求,服务端做出具体的动作,将结果回应给客户端...响应头(server header):包括搭建服务器的软件,发送响应的时间,回应数据的格式等信息,...
  • springboot设置响应状态码

    千次阅读 2019-07-05 14:54:33
    业务需要自定义http的响应状态,图中响应状态码是200,需要改成401. 使用HttpServletResponse对象直接设置状态局限比较大,可以改用以下方式,通过ResponseEntity可以返回我们需要的数据还可以自定义状态码。 @...
  • HTTP响应状态码

    千次阅读 2020-09-13 07:02:21
    HTTP响应状态码 (HTTP Status Code),也属于HTTP协议的一部分,用来标识响应的状态。响应状态码会随着响应消息一起被发送至...常见响应状态码,2**成功响应相关;3**重定向相关;4**客户端响应相关;5**服务端响应相关
  • HTTP 响应状态码规范

    千次阅读 2018-08-25 17:05:15
    响应分为五类:信息响应,成功响应,重定向,客户端错误和服务器错误。状态代码由 section 10 of RFC 2616定义 一、信息响应 100 Continue 这个临时响应表明,迄今为止的所有内容都是可行的,客户端应该继续...
  • HTTP基础:响应报文

    2019-03-31 17:36:40
    HTTP 响应报文 HTTP响应报文(Response)的结构与request的结构基本一致:由状态行、响应头部、空行...响应报文headers属性 同样适用Fiddler查看response headers,点击Inspectors tab ->Response tab ->head...
  • 给定错误堆栈对象,获取一条消息和/或关联的HTTP响应代码(404、400、401等) 我创建它是为了与 express.js 一起使用,但它应该能够处理不同类型的错误,并智能地返回 HTTP 响应代码和简单的字符串消息。 安装 npm...
  • SIP响应代码

    2016-09-13 16:34:35
    SIP响应是由一个用户代理服务器(UAS)或SIP服务器生成回复由客户端生成的请求的消息。它可能是一个正式的确认,以防止请求由UAC重发。...1XX被认为是一个临时响应,其余的最终响应。 类别 描述 动
  • //响应值存在且响应值是401 if ( err . response && err . response . status === 401 ) { // login router 跳转登录的配置 //目的:需要query形式传参 进行回跳当前页面的地址.如果是vue组件,...
  • 常用HTTP协议响应

    千次阅读 多人点赞 2017-10-25 17:11:08
    HTTP响应码,也称http状态码(HTTP Status Code),反映了web服务器处理HTTP请求状态,每一个响应码都代表了一种服务端反馈的响应状态,标识了本次请求是否成功。我们应该了解常见的响应码代表的状态,通过响应码能够...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 57,978
精华内容 23,191
关键字:

响应401