起源:

近期帮别人做项目,涉及到OAuth认证,服务端主动使token失效,要使对应用户不能再继续访问,只能重新登陆,或者重新授权。

场景:

这种场景OAuth2.0是支持的,比如用户修改了密码,那所有之前保留在各个客户端的token均失效,要求用户重新提供凭证。

原因:

在之前的项目中,一旦授权服务AuthorizationServer发放了token,所有的资源服务只会通过统一的加密解密算法,解析出token中的信息包括用户身份等,就直接使用了。这样因为不和数据库或外部存储介质交互,所以效率会比较高。以下是在所有资源服务、包括认证服务Web.config中的配置,machineKey必须相同。

  <system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
<machineKey decryptionKey="B7E121C5839A624E" validation="SHA1" validationKey="C2B8DF31AB96asd428066DFDA1A479542825F3B48865C4E47AF6A026F2" />
</system.web>

这样效率是提高了,但是每次验证不与后端(尤指存储)交互,所以token一旦发出,除非客户端主动清除或着超出有效时间,否则都有效,有一定的失窃风险。

分析:

.Net在IdentityServer3.0在用户表中使用SecurityStamp字段,作为安全标识,去识别是否失效。默认情况是没有开启验证的,否则就像之前说的每次都会和数据库交互,降低性能。关于SecurityStamp的说明,大家可以看一下这篇文章:

What is ASP.NET Identity's IUserSecurityStampStore<TUser> interface?

This is meant to represent the current snapshot of your user's credentials. So if nothing changes, the stamp will stay the same. But if the user's password is changed, or a login is removed (unlink your google/fb account), the stamp will change. This is needed for things like automatically signing users/rejecting old cookies when this occurs, which is a feature that's coming in 2.0.

    Edit: Updated for 2.0.0. So the primary purpose of the SecurityStamp is to enable sign out everywhere. The basic idea is that whenever something security related is changed on the user, like a password, it is a good idea to automatically invalidate any existing sign in cookies, so if your password/account was previously compromised, the attacker no longer has access.

In 2.0.0 we added the following configuration to hook the OnValidateIdentity method in the CookieMiddleware to look at the SecurityStamp and reject cookies when it has changed. It also automatically refreshes the user's claims from the database every refreshInterval if the stamp is unchanged (which takes care of things like changing roles etc)

文章中给出的代码如下:

app.UseCookieAuthentication(new CookieAuthenticationOptions {
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider {
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});

虽然这篇文章大致讲明白了,这是个什么东西和怎么用,但是仔细想想,还是有问题,因为我们是使用Bearer方式,这里只是Cookie,所以还差点什么。在资源服务中的配置如下:

namespace ResourceServer
{
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
app.UseOAuthBearerAuthentication(new Microsoft.Owin.Security.OAuth.OAuthBearerAuthenticationOptions());
}
}
}

所以我们应该更改的是OAuthBearerAuthenticationOptions这个对象。有找到文章参考如下:

Using bearer tokens (ASP.NET Identity 2.0) with WCF Data Services

总结:

在资源服务中,引入Microsoft.AspNet.Identity.Owin包,在Startup中,更改如下代码:

    public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
{
Provider = new OAuthBearerAuthenticationProvider()
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<UserManager, User>(
validateInterval: TimeSpan.FromMinutes(),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
}
}

查看SecurityStampValidator类的源码:

public static Func<CookieValidateIdentityContext, Task> OnValidateIdentity<TManager, TUser, TKey>(
TimeSpan validateInterval, Func<TManager, TUser, Task<ClaimsIdentity>> regenerateIdentityCallback,
Func<ClaimsIdentity, TKey> getUserIdCallback)
where TManager : UserManager<TUser, TKey>
where TUser : class, IUser<TKey>
where TKey : IEquatable<TKey>
{
.....
               var user = await manager.FindByIdAsync(userId).WithCurrentCulture();
var reject = true;
// Refresh the identity if the stamp matches, otherwise reject
if (user != null && manager.SupportsUserSecurityStamp)
{
var securityStamp =
context.Identity.FindFirstValue(Constants.DefaultSecurityStampClaimType);
if (securityStamp == await manager.GetSecurityStampAsync(userId).WithCurrentCulture())
{
reject = false;
// Regenerate fresh claims if possible and resign in
if (regenerateIdentityCallback != null)
{
var identity = await regenerateIdentityCallback.Invoke(manager, user).WithCurrentCulture();
if (identity != null)
{
// Fix for regression where this value is not updated
// Setting it to null so that it is refreshed by the cookie middleware
context.Properties.IssuedUtc = null;
context.Properties.ExpiresUtc = null;
context.OwinContext.Authentication.SignIn(context.Properties, identity);
}
}
}
}
          .....
};
}

它会自己判断token中解析出来的securityStamp是否与数据库之前保存的一致,至此,完全解决。

问题:

  • 我们之前说过的,每次请求认证都会请求数据库,降低性能。
  • 资源服务不能独立,必须与用户库绑定。

.Net Identity OAuth 2.0 SecurityStamp 使用的更多相关文章

  1. [转]An introduction to OAuth 2.0 using Facebook in ASP.NET Core

    本文转自:http://andrewlock.net/an-introduction-to-oauth-2-using-facebook-in-asp-net-core/ This is the ne ...

  2. Identity Server 4 预备知识 -- OAuth 2.0 简介

    OAuth 2.0 简介 OAuth有一些定义: OAuth 2.0是一个委托协议, 它可以让那些控制资源的人允许某个应用以代表他们来访问他们控制的资源, 注意是代表这些人, 而不是假冒或模仿这些人. ...

  3. Identity Server 4 原理和实战(完结)_----选看 OAuth 2.0 简介(上)

    https://www.yuque.com/yuejiangliu/dotnet/cg95ni 代表资源所有者的凭据 授权 Authorization Grant 授权是一个代表着资源所有者权限的凭据 ...

  4. ASP.NET WebApi OWIN 实现 OAuth 2.0

    OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用. OAuth 允许用户提供一个令牌, ...

  5. NET WebApi OWIN 实现 OAuth 2.0

    NET WebApi OWIN 实现 OAuth 2.0 OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和 ...

  6. 基于 IdentityServer3 实现 OAuth 2.0 授权服务数据持久化

    最近花了一点时间,阅读了IdentityServer的源码,大致了解项目整体的抽象思维.面向对象的重要性; 生产环境如果要使用 IdentityServer3 ,主要涉及授权服务,资源服务的部署负载的 ...

  7. 基于 IdentityServer3 实现 OAuth 2.0 授权服务【密码模式(Resource Owner Password Credentials)】

    密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码.客户端使用这些信息,向"服务商提供商"索要授权 ...

  8. 基于 IdentityServer3 实现 OAuth 2.0 授权服务【客户端模式(Client Credentials Grant)】

    github:https://github.com/IdentityServer/IdentityServer3/ documentation:https://identityserver.githu ...

  9. 我也想聊聊 OAuth 2.0 —— Access Token

    这是一篇待在草稿箱半年之久的文章 连我自己都不知道我的草稿箱有多少未发布的文章了.这应该是我在上一家公司未解散之前写的,记得当时是要做一个开发者中心,很不幸. 今天,打开草稿箱有种莫名的伤感,看到这个 ...

随机推荐

  1. 查看一个dll是否是强命名[C#]

    使用命令行工具SDK Command Prompt,键入:SN -T C:\*****.dll 就会显示出该dll具体的PublicKeyToken 数值. 如果该程序集没有强命名,则不会有Publi ...

  2. 邮件服务器日志:/var/log/maillog

    /var/log/maillog会记录包含系统上运行的邮件服务器的日志信息,比如记录 postfix 或 sendmail 运行时的日志信息 [root@localhost ~]# tail /var ...

  3. python --->字典 集合 学习笔记

    1.字典--->创建空字典:dict={} broa=["李宁",”耐克“,“阿迪达斯”,“鱼c工作室”] sloga=[“A”,“B”,“C”,“D”] dict={&qu ...

  4. windowsError错误码详解

    WindowsError的错误代码详解 0操作成功完成. 1功能错误. 2系统找不到指定的文件. 3系统找不到指定的路径. 4系统无法打开文件. 5拒绝访问. 6句柄无效. 7存储控制块被损坏. 8存 ...

  5. Android学习之AutoCompleteTextView

    AutoCompleteTextView有点类似于EditText和Spinner的混合体.当用户在输入时,如果应用程序的文本输入框中使用了自动完成控件,预输入文本被看作是一个前缀过滤器,与用户当前输 ...

  6. PHP关于按位取反结果的推导过程

    哎呀几年过去,都快把大学学的计算机导论的知识给忘完了,现在来回顾一下按位去反的流程: <?php /** 首先来补充一下基础知识: php中有4个位运算,分别是&与 |或 ^异或 ~取反 ...

  7. WebService连接sql serever并使用Android端访问数据

    一.下载sql serever(真真难下) 建立数据库 二.创建WebService VS2015中新建项目,进行连接调试 1. 服务资源管理文件->数据连接->新建连接 2. 继续-&g ...

  8. [OpenGL]用OpenGL制作动画

    //在窗口内绘制一个移动的矩形 /*我们通常还可以用OpenGL程序创建动画效果,这里我们利用前面的例子,绘制正方形,并使这个正方形在窗口的边框反弹.这里需要创建一个循环,在每次调用显示回调函数之前改 ...

  9. [转]C++中模板的特化与偏特化

    转载自:http://hi.baidu.com/klcdyx2008/blog/item/5adbf77b79f316f90bd1873c.html 1.引言C++中的模板分为类模板和函数模板,虽然它 ...

  10. echarts - 特殊需求实现方案汇总

    五分钟上手echarts echarts中 设置x||y轴文案.提示文字等为固定字数,超出显示"..." 关于echarts下钻功能的一些总结.js echarts - 特殊需求实 ...