c# – 未使用OWIN承载令牌对用户登录进行身份验证

前端之家收集整理的这篇文章主要介绍了c# – 未使用OWIN承载令牌对用户登录进行身份验证前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用MVC应用程序.登录由Web API处理.

我面临的问题是,当我点击MVC应用程序中的“登录”按钮时,API正在生成令牌以及用户信息.但是我无法在视图中显示用户信息.

以下代码位于MVC App的AccountController中

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(Loginviewmodel model)
{
   string token = Token.GetToken(Token.GRANT_TYPE,model.Email,model.Password,Token.CLIENT_ID,Token.CLIENT_SECRET);

  //token has the appropriate data if I debug it

   if (!string.IsNullOrEmpty(token))
       return RedirectToAction("Index","Home");

   return View(model);
}

然后在视图中我有

@if (Request.IsAuthenticated)
{
  <p>@User.Identity.GetUserName()</p> //this line is always blank
}

API看起来像这样

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{

        var allowedOrigin = context.OwinContext.Get<string>("as:clientAllowedOrigin");

        if (allowedOrigin == null) allowedOrigin = "*";

        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin",new[] { allowedOrigin });

        using (AuthRepository _repo = new AuthRepository())
        {
            ApplicationUser user = await _repo.FindUser(context.UserName,context.Password);

            if (user == null)
            {
                context.SetError("invalid_grant","The user name or password is incorrect.");
                return;
            }
        }

        var identity = new ClaimsIdentity(context.Options.AuthenticationType);

        identity.AddClaim(new Claim(ClaimTypes.Name,context.UserName));
        identity.AddClaim(new Claim(ClaimTypes.Role,"user"));
        identity.AddClaim(new Claim("sub",context.UserName));

        var props = new AuthenticationProperties(new Dictionary<string,string>
            {
                {
                    "as:client_id",(context.ClientId == null) ? string.Empty : context.ClientId
                },{
                    "userName",context.UserName
                },{
                    "email",});

        var ticket = new AuthenticationTicket(identity,props);
        context.Validated(ticket);
}

有人能告诉我为什么请求没有被认证?我错过了什么

解决方法

从你的例子中我看起来有些不对劲的事情

第一部分:您的登录方法

惯例是使用GrantResourceOwnerCredentials作为端点(/ api / token),它接收凭证并返回访问令牌.

按照惯例,此端点替换Login(Loginviewmodel)方法.显然你不应该使用Login()方法,但我怀疑你是.

>如果您使用的是Login方法,它只会返回原始的,未更改的View Cre Model with Credentials.您的Loginviewmodel类可能包含令牌属性,但您没有填充它.因此,登录方法会对您的用户进行身份验证,但不会对其进行授权,因为用户永远不会获取其访问令牌.
>您的GrantResourceOwnerCredentials方法确实返回令牌并填充声明.但是,您是否有任何客户端逻辑来存储访问令牌并在每个请求中发送它?
>除非您的令牌采用JWT(Json Web令牌)之类的格式,否则我怀疑取消加密令牌以访问声明(例如userName / email)将是一项重大挑战.这意味着,除非是JWT,否则客户端从访问令牌中提取声明并不容易.

第二部分:有人可以告诉我为什么请求没有被认证?

您正在通过身份验证.但这不是表单身份验证.没有Cookie.当API返回访问令牌时,Razor Calls to Identity将无法工作.

在典型的Forms Auth模型中:

凭证被发送和验证(经过身份验证).如果验证成功,则用户被授权(给定访问权限),其客户端cookie具有加密的访问信息和声明. OWIN Middle-ware在每个请求上读取Cookie并填充httpContext(Identity是httpContext对象上的属性.)

访问令牌工作流程:

非常相似,除了,因为没有Cookie,并且API和客户端View之间没有连接,而不是View Models中返回的数据.每次OWIN中间件读取访问令牌时,除了在服务器端(Web API)之外,不会填充httpContext.

所以,剃刀召唤

@User.Identity.GetUserName()

会出现空洞.

解决方案:在客户端上获取并存储用户信息

如果您需要来自服务器的用户信息,您应该在客户端上缓存用户名(以及您需要的任何其他信息).

在客户端浏览器上存储用户信息的方法

>会话存储
>本地存储
> JavaScript单例类(如Angular服务)

获取用户名方法

>存储用户输入凭据时获得的用户名(如果身份验证失败,请清除它)
>有一个专用的终点(API方法)来返回您想要的用户信息
>返回JWT的索赔.

如果您更改令牌类型(在Global.asax或Startup.cs中 – 取决于您配置的方式)以使用Jason Web Tokens,客户端将能够取消您的令牌编码并将声明作为JSON数组读取.

>最后一个选项:您可以同时使用访问令牌和Cookie.您可以返回访问令牌并创建cookie.在配置Web API时,为Web API禁止cookie auth.>最后的想法:访问令牌用于额外的安全级别(cookie更容易受到攻击).但是您使用Access Tokens的目的是什么?如果您正在创建与AngularJS类似的SPA(单页应用程序),则此类安全性更为重要.否则,Cookie Auth是一个更简单的工作流程,除非您觉得需要额外的安全性,否则Cookie更可取.

猜你在找的C#相关文章