var user = UserManager.Find(...);
ClaimsIdentity identity = UserManager.CreateIdentity(
user, DefaultAuthenticationTypes.ApplicationCookie );
var claim1 = new Claim(
ClaimType = ClaimTypes.Country, ClaimValue = "Arctica", UserId = user.Id );
identity.AddClaim(claim1);
AuthenticationManager.SignIn(
new AuthenticationProperties { IsPersistent = true }, identity );
var claim2 = new Claim(
ClaimType = ClaimTypes.Country, ClaimValue = "Antartica", UserId = user.Id );
identity.AddClaim(claim2);
claim1 和 claim2 仅在ClaimsIdentity 用户登录 时跨请求持久保存。换句话说,当用户通过调用 SignOut()注销时,两个声明也会被删除,因此下次该用户 < strong="">登录,它不再是这两个声明的成员(我假设两个声明不再存在)
claim2 在请求中持续存在的事实(即使 authentication cookie 在 claim2 被添加到用户时已经创建)表明claims 不会通过authentication cookie 在请求中保留,而是通过其他方式保留。
那么 claims 如何跨请求持久化?
编辑:
1) 据我所知,类型声明 IdentityUserClaim 从未在 < strong="">cookie?
var user = UserManager.Find(...);
/* claim1 won't get persisted in a cookie */
var claim1 = new IdentityUserClaim
{ ClaimType = ClaimTypes.Country, ClaimValue = "Arctica", UserId = user.Id };
user.Claims.Add(claim1);
ClaimsIdentity identity = UserManager.CreateIdentity(
user, DefaultAuthenticationTypes.ApplicationCookie );
AuthenticationManager.SignIn(
new AuthenticationProperties { IsPersistent = true }, identity );
如果我的假设是正确的,这就是为什么 IdentityUserClaim 实例没有保存在 cookie 中的原因,因为假设这些声明应该存储在 DB 中,因此可以在 后续请求 中从 DB 中检索,而 claims of type Claim 通常不存储在 DB 中,因此为什么需要将它们保存在 cookie 中?
2)
If you'd like to have a deeper look how it all works, check out the source code of Katana Project
我认为 Asp.net Identity 2 不是Katana 项目 的一部分(也就是说,我看到有人问微软什么时候会发布源代码对于 Asp.Net Identity,即使 Katana 源代码 已经可用)?!
谢谢
最佳答案
好问题。甚至让我做了一个小实验。
这一行:
AuthenticationManager.SignIn(
new AuthenticationProperties { IsPersistent = true }, identity );
不设置 cookie。仅为以后的回调设置 Identity 对象。
只有当控制传递给中间件和一些 OWIN 内部方法称为 Response.OnSendingHeaders 时才会设置 Cookie。
所以您的代码只是在存储在内存中供以后用户使用的identity 对象上添加claim2。理论上,您甚至可以在完成 AuthenticationManager.SignIn 之后设置 claim1。无论如何它都会保留在 cookie 中。
如果您尝试在 Controller 中添加这样的 cliam:
public ActionResult AddNonPersistedClaim()
{
var identity = (ClaimsIdentity)ClaimsPrincipal.Current.Identity;
identity.AddClaim(new Claim("Hello", "World"));
return RedirectToAction("SomeAction");
}
此声明不会设置在 cookie 中,您将不会在下一个请求中看到它。
如果您想更深入地了解它是如何工作的,请查看 Katana Project 的源代码,查看 Microsoft.Owin.Security 和 Microsoft.Owin.Security.Cookies 项目。连同 Microsoft.Owin.Net45 项目中的 AuthenticationManager。
更新
回答您的编辑 1 - IdentityUserClaim 确实持久保存到数据库中,这是您可以将持久声明分配给用户的方式。您通过 UserManager
await userManager.AddClaimAsync(userId, new Claim("ClaimType", "ClaimValue"));
这会在您的数据库表中创建代表 IdentityUserClaim 的记录。下次用户登录时,这些声明将从数据库中读取并添加到身份中,并通过属性 .Claims 或方法 在 .ClaimsIdentity.Current 上可用>.HasClaim()
IdentityUserClaim 不执行任何其他操作 - 只是将 Claim 对象序列化到数据库中的方法。您通常不会直接访问这些,除非您想“赤手空拳”并在 UserManager 之外自己写入该表。
换句话说 - 身份不设置 cookie。 OWIN 创建 cookie。看看this piece of code :
public async Task SignInAsync(IAuthenticationManager authenticationManager, ApplicationUser applicationUser, bool isPersistent)
{
authenticationManager.SignOut(
DefaultAuthenticationTypes.ExternalCookie,
DefaultAuthenticationTypes.ApplicationCookie,
DefaultAuthenticationTypes.TwoFactorCookie,
DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie,
DefaultAuthenticationTypes.ExternalBearer);
var identity = await this.CreateIdentityAsync(applicationUser, DefaultAuthenticationTypes.ApplicationCookie);
identity.AddClaim(new Claim(ClaimTypes.Email, applicationUser.Email));
authenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}
此处身份验证管理器是 OWIN 的一部分。 Identity 是 System.Security.Claims 的一部分。所有属于 Identity 项目的都是 CreateIdentityAsync 方法 - 基本上是将用户从数据库转换为 ClaimsIdentity 以及所有持久化的角色和声明。
回答您的编辑 2:您是对的,AspNet Identity 不是 Katana 项目的一部分,但 Identity 使用 OWIN(Katana 的一部分)进行 cookie 处理和授权。 Identity 项目主要处理用户/角色/声明持久性和用户管理,例如锁定、用户创建、发送带密码重置的电子邮件、2FA 等。
令我惊讶的是 ClaimsPrincipal连同 ClaimsIdentity和 Claim是在 OWIN 或 Identity 之外可用的 .Net 框架的一部分。这些不仅在 Asp.Net 中使用,而且在 Windows 应用程序中使用。好在 .Net 现在有开源,你可以浏览所有这些——让你更好地理解它们是如何协同工作的。此外,如果您正在进行单元测试,了解内部结构是非常宝贵的,因此您可以在不使用模拟的情况下去除所有功能。
关于c# - 跨请求持久声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25292137/
我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA
在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这
对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
我是Ruby的新手。我试过查看在线文档,但没有找到任何有效的方法。我想在以下HTTP请求botget_response()和get()中包含一个用户代理。有人可以指出我正确的方向吗?#PreliminarycheckthatProggitisupcheck=Net::HTTP.get_response(URI.parse(proggit_url))ifcheck.code!="200"puts"ErrorcontactingProggit"returnend#Attempttogetthejsonresponse=Net::HTTP.get(URI.parse(proggit_url)
在我的路线文件中我有:match'graphs/(:id(/:action))'=>'graphs#(:action)'如果是GET请求(工作)或POST请求(不工作),我想匹配它我知道我可以使用以下方法在资源中声明POST请求:post'/'=>:show,:on=>:member但是我怎样才能为比赛做到这一点呢?谢谢。 最佳答案 如果你同时想要POST和GETmatch'graphs/(:id(/:action))'=>'graphs#(:action)',:via=>[:get,:post]编辑默认值可以设置如下match'g
我有一个ruby程序,我想接受用户创建的方法,并使用该名称创建一个新方法。我试过这个:defmethod_missing(meth,*args,&block)name=meth.to_sclass我收到以下错误:`define_method':interningemptystring(ArgumentError)in'method_missing'有什么想法吗?谢谢。编辑:我以不同的方式让它工作,但我仍然很好奇如何以这种方式做到这一点。这是我的代码:defmethod_missing(meth,*args,&block)Adder.class_evaldodefine_method