2017-06-06 136 views
1

我将基于令牌的身份验证添加到我的OWIN中间件,并可以生成令牌。但是在使用时,带有Authorize属性的API调用令牌总是会得到“授权已被拒绝。”虽然没有Authorize属性,但它工作正常。这是我的startup.cs和控制器方法。任何想法,有什么不对?“消息”:“此请求的授权已被拒绝。” OWIN中间件

startup.cs

public void Configuration(IAppBuilder app) 
      { 
       var issuer = ConfigurationManager.AppSettings["issuer"]; 
       var secret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["secret"]); 
       app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions 
       { 
        AuthenticationType = DefaultAuthenticationTypes.ExternalBearer, 
        AllowInsecureHttp = true, 
        TokenEndpointPath = new PathString("/token"), 
        AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30), 
        Provider = new SimpleAuthProvider(), 
        AccessTokenFormat = new JwtFormat(issuer) 
       }); 
       app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions 
       { 
        AuthenticationType = DefaultAuthenticationTypes.ExternalBearer, 
        AuthenticationMode = AuthenticationMode.Active, 
        AllowedAudiences = new[] { "*" }, 
        IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[] 
        { 
         new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret) 
        } 
       }); 
       container = BuildDI(); 
       var config = new HttpConfiguration(); 
       config.Formatters.XmlFormatter.UseXmlSerializer = true; 
       config.MapHttpAttributeRoutes(); 
       config.SuppressDefaultHostAuthentication(); 
       config.Filters.Add(new HostAuthenticationFilter(DefaultAuthenticationTypes.ExternalBearer)); 
       config.DependencyResolver = new AutofacWebApiDependencyResolver(container); 
       app.UseCors(CorsOptions.AllowAll); 
       app.UseSerilogRequestContext("RequestId"); 
       app.UseAutofacMiddleware(container); 
       app.UseAutofacWebApi(config); 
       app.UseWebApi(config); 
       RegisterShutdownCallback(app, container); 
      } 

public class SimpleAuthProvider: OAuthAuthorizationServerProvider 
     { 
      public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) 
      { 

       if (context.UserName != context.Password) 
       { 
        context.SetError("invalid_grant", "The user name or password is incorrect"); 
        context.Rejected(); 
        return Task.FromResult<object>(null); 
       } 

       var ticket = new AuthenticationTicket(SetClaimsIdentity(context), new AuthenticationProperties()); 
       context.Validated(ticket); 

       return Task.FromResult<object>(null); 
      } 

      public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) 
      { 
       context.Validated(); 
       return Task.FromResult<object>(null); 
      } 

      private static ClaimsIdentity SetClaimsIdentity(OAuthGrantResourceOwnerCredentialsContext context) 
      { 
       var identity = new ClaimsIdentity(DefaultAuthenticationTypes.ExternalBearer); 
       identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName)); 
       return identity; 
      } 
     } 

API控制器的方法:

[HttpGet] 
     [Route("sampleroute")] 
     [Authorize] 
     public async Task<HttpResponseMessage> GetSamples(string search) 
     { 
      try 
      { 

       HttpResponseMessage response; 
       using (HttpClient client = new HttpClient(Common.CreateHttpClientHandler())) 
       { 
        response = await client.GetAsync("test url"); 
       } 
       var result = response.Content.ReadAsStringAsync().Result; 
       Samples[] sampleArray = JsonConvert.DeserializeObject<Samples[]>(result); 
       var filteredSamples = sampleArray .ToList().Where(y => y.NY_SampleName.ToUpper().Contains(search.ToUpper())).Select(n=>n); 
       log.Information("<==========Ended==========>"); 
       return Request.CreateResponse(HttpStatusCode.OK,filteredSamples); 

      } 
      catch (Exception ex) 
      { 
       log.Error($"Error occured while pulling the Samples: {ex.ToString()}"); 
       return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.ToString()); 
      } 
     } 
+0

只是为了确定。在授权属性中是否包含令牌和持有者? I.E.授权:持票人“令牌” – allencage

+0

@allencage不,我没有。我怎么做? – user3154990

+0

@RuardvanElburg我在邮递员测试...我通过调用localhost/api/token获取令牌,并将它用于具有Authorize属性的API调用。 lcoalhost/api是我的主机网址。 – user3154990

回答

1

这可能是允许的观众的问题。 此处

app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions 
{ 
    ...  
    AllowedAudiences = new[] { "*" }, 
    ... 
} 

您设置允许的受众群体。将根据AllowedAudiences列表检查令牌aud索赔。但是你绝不会将任何观众添加到令牌中。

在我们的项目我使用的CustomJwtFormat基于在http://bitoftech.net/2014/10/27/json-web-token-asp-net-web-api-2-jwt-owin-authorization-server/

令牌示出将与呼叫生成的代码来

var token = new JwtSecurityToken(_issuer, audienceId, data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingKey); 

第二个参数是负责在JWT的aud权利要求:

https://msdn.microsoft.com/en-us/library/dn451037(v=vs.114).aspx

受众 类型:System.String

如果此值不为空,则会添加{aud,'audience'}声明。

在令牌授权中设置aud声明之后应该可以正常工作。

+0

感谢队友,我在创建导致问题的令牌时传递null给观众。 – user3154990

+0

很高兴帮助:) – jps

1

从我的理解,你需要添加标题:授权:承载 “令牌”。 如果您还没有修改的授权请求的默认实现的步骤是这些:

/api/Account/Register 
  • 邮政/令牌以下项目:
      在端点

      1. 注册用户

      2. grant_type:密码
      3. 用户名:“您注册的用户名”
      4. 密码:
  • 您将收到一个令牌响应
  • 复制该令牌,并创建一个请求给您类型的[授权]过滤器固定的方法:“在你的用户注册的密码” :

    Authorization: Bearer "the_token_you_copied_earlier" 
    

    不用说,这可能是很容易为你,如果你使用的邮递员或提琴手发出和接收请求,因为它显示了你的一切是如何工作的。

  • +0

    @allenceage我在这里发布之前完全相同的方式,并用尽了想法。 :) – user3154990

    +0

    @ user3154990我的解决方案适用于开箱即用的OAuth,从我在代码中看到的未使用默认实现的方式工作。如果您尝试构建的授权不是强制性的,请尝试默认方法。 – allencage

    相关问题