【问题标题】:Generate Identity from bearer token从不记名令牌生成身份
【发布时间】:2015-11-30 17:22:23
【问题描述】:

有没有办法在 asp.net 中手动获取 Bearer Token 字符串并将其转换为 Identity 对象?

干杯, 阿齐兹

【问题讨论】:

标签: c# asp.net asp.net-web-api asp.net-identity asp.net-web-api2


【解决方案1】:

令牌仅包含声明,仅用于对资源进行身份验证。如果其中一个声明包含用户信息,您可以创建一个身份并将声明分配给它。

public void ValidateBearerToken(OwinContext context)
{
    try
    {
       var tokenHandler = new JwtSecurityTokenHandler();
       byte[] securityKey = GetBytes("some key"); //this should come from a config file

       SecurityToken securityToken;

       var validationParameters = new TokenValidationParameters()
       {
          ValidAudience = "http://localhost:2000", 
          IssuerSigningToken = new BinarySecretSecurityToken(securityKey),
          ValidIssuer = "Self"
       };

       var auth = context.Request.Headers["Authorization"];

       if (!string.IsNullOrWhiteSpace(auth) && auth.Contains("Bearer"))
       {
          var token = auth.Split(' ')[1];

          var principal = tokenHandler.ValidateToken(token, validationParameters, out securityToken);

          context.Request.User = principal;
       }
   }
   catch (Exception ex)
   {
       var message = ex.Message;
   }
}

【讨论】:

  • 你能扩展一下吗?如何从字符串(原始令牌)到提取信息。
  • 这将验证您的令牌并设置声明原则。然后,您只需将声明添加到 pricinple.Claims 列表中。
  • 我使用的是 SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider 而不是 Jwt 安全令牌
【解决方案2】:

首先,您需要根据令牌创建一些声明,然后创建 ClaimsIdentity 并使用它来授权用户。

public ActionResoult Login(string token)
{
    if(_tokenManager.IsValid(token))         
    {
        // optionally you have own user manager which returns roles and user name from token
        // no matter how you store users and roles
        var user=_myUserManager.GetUserRoles(token);

        // user is valid, going to authenticate user for my App
        var ident = new ClaimsIdentity(
            new[] 
            {  
                // adding following 2 claim just for supporting default antiforgery provider
                new Claim(ClaimTypes.NameIdentifier, token),
                new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string"),

                // an optional claim you could omit this 
                new Claim(ClaimTypes.Name, user.Username),

                // populate assigned user's role form your DB 
                // and add each one as a claim  
                new Claim(ClaimTypes.Role, user.Roles[0]),
                new Claim(ClaimTypes.Role, user.Roles[1]),
                // and so on
            },
            DefaultAuthenticationTypes.ApplicationCookie);

        // Identity is sign in user based on claim don't matter 
        // how you generated it             
        HttpContext.GetOwinContext().Authentication.SignIn(
            new AuthenticationProperties { IsPersistent = false }, ident);

        // auth is succeed, just from a token
        return RedirectToAction("MyAction"); 
    }
    // invalid user        
    ModelState.AddModelError("", "We could not authorize you :(");
    return View();
}

现在您也可以使用Authorize 过滤器了:

[Authorize]
public ActionResult Foo()
{
}

// since we injected user roles to Identity we could do this as well
[Authorize(Roles="admin")]
public ActionResult Foo()
{
    // since we injected our authentication mechanism to Identity pipeline 
    // we have access current user principal by calling also
    // HttpContext.User
}

我还鼓励您从我的 github 存储库中查看 Token Based Authentication Sample 作为一个非常简单的工作示例。

【讨论】:

  • 没有 _myUserManager.GetUserRoles(token);... 方法。我正在使用公共类 SimpleAuthorizationServerProvider :OAuthAuthorizationServerProvider - 这有帮助吗?
  • _myUserManager 就是一个例子。展示如何使用自己的类来生成声明并基于用户登录。在这个例子中,我使用_myUserManager 来提取当前用户角色,您可以实现自己的类。用户名和角色只是简单的字符串。如果您没有用户名或角色,则可选。如果您查看我的 github 存储库,您会看到我如何只使用一个字符串来授权用户。
  • 我没有当前用户上下文。我需要从字符串令牌转到用户。我需要知道 _myUserManager.GetUserRoles(token); 中的 locic;
  • 那么您如何存储用户数据?在数据库中?您的用户是否有角色?
  • 我使用默认的 aspnet_user 表。但是,令牌生成由 Microsoft.Owin.Security.OAuth 处理;努吉特。令牌不存储在数据库中,所以我不能只是将引用拉给用户。
【解决方案3】:

这是一个很老的问题,但我认为答案仍然缺失。我能够使用以下行重新生成 Principal

var ticket = Startup.OAuthOptions.AccessTokenFormat.Unprotect(accessToken);
var identity = ticket.Identity;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-11
    相关资源
    最近更新 更多