12

我正在尝试了解有关MVC 5 OWIN登录的声明。我尽量保持简单。我从MVC模板开始,插入我的声明代码(见下文)。我在View中使用@ Html.AntiForgeryToken()助手时出现错误。MVC 5 OWIN登录声明和AntiforgeryToken。我错过了ClaimsIdentity提供者吗?

错误:

A claim of type 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier' or 
'http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovid  
er' was not present on the provided ClaimsIdentity. 

To enable anti-forgery token support with claims-based authentication, please verify that 
the configured claims provider is providing both of these claims on the ClaimsIdentity 
instances it generates. If the configured claims provider instead uses a different claim 
type as a unique identifier, it can be configured by setting the static property 
AntiForgeryConfig.UniqueClaimTypeIdentifier. 

Exception Details: System.InvalidOperationException: A claim of type 
'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier' or 
'http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider' was 
not present on the provided ClaimsIdentity. To enable anti-forgery token 
support with claims-based authentication, please verify that the configured claims provider 
is providing both of these claims on the ClaimsIdentity instances it generates. 
If the configured claims provider instead uses a different claim type as a unique 
identifier, it can be configured by setting the static property 
AntiForgeryConfig.UniqueClaimTypeIdentifier. 

Source Error: 
Line 4:  using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new 
{ id = "logoutForm", @class = "navbar-right" })) 
Line 5:  { 
Line 6:  @Html.AntiForgeryToken() 

登录后行动

// POST: /Account/Login 
[HttpPost] 
[AllowAnonymous] 
[ValidateAntiForgeryToken] 
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl) 
{ 
    if (!ModelState.IsValid) 
    { 
     return View(model); 
    } 

    var claims = new List<Claim> 
    { 
     new Claim(ClaimTypes.Name, "Brock"), 
     new Claim(ClaimTypes.Email, "[email protected]") 
    }; 
    var id = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie); 

    var ctx = Request.GetOwinContext(); 
    var authenticationManager = ctx.Authentication; 
    authenticationManager.SignIn(id); 

    return RedirectToAction("Welcome"); 
} 

_LoginPartial.cshtml

@using Microsoft.AspNet.Identity 
@if (Request.IsAuthenticated) 
{ 
    using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" })) 
    { 
    @Html.AntiForgeryToken() 

    <ul class="nav navbar-nav navbar-right"> 
     <li> 
      @Html.ActionLink("Hello " + User.Identity.GetUserName() + "!", "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" }) 
     </li> 
     <li><a href="javascript:document.getElementById('logoutForm').submit()">Log off</a></li> 
    </ul> 
    } 
} 

我已经tryed设置ClaimTypes.NameIdentifierlike in this SO answer

protected void Application_Start() 
{ 
    AreaRegistration.RegisterAllAreas(); 
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
    RouteConfig.RegisterRoutes(RouteTable.Routes); 
    BundleConfig.RegisterBundles(BundleTable.Bundles); 

    AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier; 
} 

然后我 “只?”得到这个错误

A claim of type 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier' was 
not present on the provided ClaimsIdentity. 

我想保留antiforgeryToken,因为它可以帮助防止跨站点脚本。

回答

13

您的要求标识不具有ClaimTypes.NameIdentifier,你应该增加更多的进入要求数组:

var claims = new List<Claim> 
{ 
    new Claim(ClaimTypes.Name, "username"), 
    new Claim(ClaimTypes.Email, "[email protected]"), 
    new Claim(ClaimTypes.NameIdentifier, "userId"), //should be userid 
}; 

要映射信息权利要求更多的纠正:

ClaimTypes.Name => map to username 
ClaimTypes.NameIdentifier => map to user_id 

由于用户名是唯一同时,因此您可以使用username进行防伪标记支持。

+1

我不知道映射是干什么的。首先,我也插入了'NameIdentifier',但得到了同样的错误。然后我尝试在Global.asax.cs中添加,但不知道它的作用,但现在它可以工作。也许它和你的映射一样? Global.asax.cs .: AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Name; AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Email; AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier; – radbyx

12

在你Application_Start(),指定为使用哪个ClaimNameIdentifier

public class MvcApplication : System.Web.HttpApplication 
{ 
    protected void Application_Start() 
    { 
     ... 

     System.Web.Helpers.AntiForgeryConfig.UniqueClaimTypeIdentifier = 
      System.Security.Claims.ClaimTypes.NameIdentifier; 

     ... 
    } 
} 

参见:http://brockallen.com/2012/07/08/mvc-4-antiforgerytoken-and-claims/

+0

感谢特拉维斯,这立即解决了我的问题....应用自动0到OWIN Asp.net的经验 –

3

AntiForgeryConfig解决它是设置AntiForgeryConfig使用其他

的一种方式ClaimType。

protected void Application_Start() 
{ 
    AreaRegistration.RegisterAllAreas(); 

    WebApiConfig.Register(GlobalConfiguration.Configuration); 
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
    RouteConfig.RegisterRoutes(RouteTable.Routes); 
    BundleConfig.RegisterBundles(BundleTable.Bundles); 

    AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Email; 
} 

添加的NameIdentifier和IdentityProvider ClaimTypes

或者,您可以添加的NameIdentifier和IdentityProvider ClaimTypes到您的权利要求。

List<Claim> _claims = new List<Claim>(); 
_claims.AddRange(new List<Claim> 
{ 
    new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", _user.Email)), 
    new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", _user.Email) 
}) 

参见:https://stack247.wordpress.com/2013/02/22/antiforgerytoken-a-claim-of-type-nameidentifier-or-identityprovider-was-not-present-on-provided-claimsidentity/

1

我用此上的Global.asax.cs的Application_Start()和解决了错误:

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes。名称;

0

我有一个类似的问题,这原来是cookie相关;我同时开发了两个MVC站点,并且因为ASP.Net站点默认使用相同的cookie名称,所以这两个站点互相干扰。清除cookie解决了问题。我的answer here还有更多。