18

我的 Angular 应用程序正在使用文章系列http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net中概述的不记名令牌-身份/。我已经按照分叉示例在访问令牌过期时无缝刷新令牌(通过 401 http 代码)。

我的问题是如何根据确定的角色确定承载令牌是否已过期或只是未经授权?

例如,我的 web api 方法具有属性 [Authorize(Roles="Admin")]。当我调用它时,我得到了预期的 401 错误。但是,当我的访问令牌过期并且我进行另一个 Web api 方法调用时,它也会返回 401 错误。这是我的拦截器中的 responseError 处理程序:

        responseError: function (rejection) {
            var deferred = q.defer();
            if (rejection.status === 401) {
                var authService = $injector.get('authService');
                authService.refreshToken().then(function (response) {
                    _retryHttpRequest(rejection.config, deferred);
                }, function () {
                    authService.logOut();
                    $location.path('/dashboard');
                    deferred.reject(rejection);
                });
            } else {
                deferred.reject(rejection);
            }
            return deferred.promise;
        }

我在玩不同的东西,但基本上,我想刷新我的令牌并在访问令牌过期时重新发送我的请求;但是,如果由于指定的角色而确实是被拒绝的请求,我不想刷新我的令牌。

有什么想法吗?

4

1 回答 1

15

正如我在对 Cory Silva 评论的回复中所指出的,Web API Authorize 属性将始终返回 401 未经授权的身份验证和授权。

请参阅下面的文章和线程:

http://leastprivilege.com/2014/10/02/401-vs-403/

为什么AuthorizeAttribute会重定向到登录页面进行认证和授权失败?

看起来有两种选择:

  1. 当我将从我的授权服务器检索到的令牌存储在 localStorage 中时,我还会存储令牌的过期时间。在拦截器 responseError 函数中,我将存储的令牌过期时间与当前日期时间进行比较。如果确定过期,刷新令牌并重新发送请求。

    responseError: function (rejection) {
        var deferred = q.defer();
    
        if (rejection.status === 401) {
            var tokenExpired = false;
            var authData = localStorage.get('authorizationData');
            if (authData) {
                tokenExpired = moment().isAfter(authData.expiration);
            }
    
            if (tokenExpired) {
                var authService = auth;//$injector.get('authService');
                authService.refreshToken().then(function (response) {
                    _retryHttpRequest(rejection.config, deferred);
                }, function () {
                    authService.logOut();
                    $state.go('error');
                    deferred.reject(rejection);
                });
            }
            else {
                $state.go('error');
                deferred.reject(rejection);
            }
        } else {
            $state.go('error');
            deferred.reject(rejection);
        }
        return deferred.promise;
    }
    
  2. 使用我上面引用的 stackoverflow 线程中接受的答案并创建我自己的 AuthorizeAttribute 来确定令牌过期与未经授权的访问。

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class AuthorizeAttribute : System.Web.Http.AuthorizeAttribute
    {
        protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
        {
            if (actionContext.RequestContext.Principal.Identity.IsAuthenticated)
            {
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Forbidden);
            }
            else
            {
                base.HandleUnauthorizedRequest(actionContext);
            }
        }
    }
    

我想我将使用选项 2,以便客户端更清楚错误代码。

于 2014-11-13T02:05:19.197 回答