ASP.NET Core的无状态身份认证框架IdentityServer4
Identity Server 4是IdentityServer的最新版本,它是流行的OpenID Connect和OAuth Framework for .NET,为ASP.NET Core和.NET Core进行了更新和重新设计。认证原理基于JWT,符合JWT流程。关于Identity Server 4的介绍和使用,网上已经很多了,一搜一大堆,本篇文章就不在介绍,这里有几篇文章还不错,作为一个参考:
1,《ASP.NET Core的身份认证框架IdentityServer4--入门》,这篇文章是翻译的国外的一篇文章,对于入门很有启发,英文原文地址:https://www.scottbrady91.com/Identity-Server/Getting-Started-with-IdentityServer-4
2,《使用JWT搭建分布式无状态身份认证系统》,这篇文章介绍JWT,以及怎么不引用Identity Server 4,手动写JWT认证服务。了解一下JWT原理和代码实现即可,如果在实际项目中用,不必再“造轮子”。
3,《IdentityServer4 中文文档与实战》,这是按照官方文档来研究的系列文章,从入门到实践。
本篇文章使用的环境:VS2017,15.9.11,目标框架:.NET Core 2.2
在项目中使用的步骤:
1,新建一个空的解决方案
2,在解决方案里新建项目,选择ASP.NET Core Web应用程序
3,目标框架选择 Core 2.2 (或其他的Core版本),选择“应用程序(模型视图控制器)”
4,打开项目属性,选择“调试”选项,删除默认的启动项
5,创建一个新的启动项,名称定为:WebAPPHost,把端口指定到5002(或者其他不与本地冲突的端口)
6,生成的launchSettings.json如下
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:31509",
"sslPort": 44328
}
},
"profiles": {
"WebAppHost": {
"commandName": "Project",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:5002"
}
}
}
7,删除不必要的文件、文件夹。(作为服务提供的项目,只提供API接口,不需要页面)
8,在NuGet中引入IdentityServer 4
9,新建一个文件夹IdentityServer,用于放IdentityServer相关的文件。
9.1首先创建一个IdentityServerClients类,定义两个方法:IEnumerable<Client> GetClients() 和 List<TestUser> GetTestUsers()
GetClients方法是IdentityServer客户端(访问控制列表)集合,GetTestUsers方法是定义IdentityServer的测试用户。代码如下:
public class IdentityServerClients
{
/// <summary>
/// IdentityServer客户端(访问控制列表)
/// </summary>
/// <returns></returns>
public static IEnumerable<Client> GetClients()
{
var list = new List<Client>
{
new Client
{
ClientId = "client",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
AllowedScopes = {"WebAppAPI" },//添加允许访问API范围
AllowOfflineAccess = true,
AccessTokenLifetime = * ,
RefreshTokenExpiration = TokenExpiration.Sliding,
SlidingRefreshTokenLifetime = * ,
RefreshTokenUsage = TokenUsage.ReUse,
ClientSecrets =
{
new Secret("D7896FC26CAC97942DEF0402322524BB".Sha256())
}
}
}; return list;
} /// <summary>
/// IdentityServer的测试用户
/// </summary>
/// <returns></returns>
public static List<TestUser> GetTestUsers()
{
List<TestUser> Testers = new List<TestUser>()
{
new TestUser()
{
SubjectId = "",
Password ="",
Username = "admin001"
},
new TestUser()
{
SubjectId = "",
Password ="",
Username = "admin002"
}
}; return Testers;
}
}
9.2 创建一个IdentityServerResources类,定义IdentityServer认证的Resources,代码如下:
public class IdentityServerResources
{
/// <summary>
/// 创建允许访问的API资源
/// </summary>
/// <returns></returns>
public static IEnumerable<ApiResource> GetApiResources()
{
List<ApiResource> resources = new List<ApiResource>()
{
new ApiResource("WebAppAPI", "测试的API"),//定义API的访问范围名称(Scope)
}; return resources;
} /// <summary>
/// 创建认证的资源
/// </summary>
/// <returns></returns>
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResources.Email(),
new IdentityResources.Address(),
new IdentityResources.Phone()
};
}
}
9.3 创建一个ResourceOwnerPasswordValidator类,这个类的作用是自定义用户登录:从自己的数据库中验证用户,或者其它项目验证用户。
一个例子:假设项目的用户数据库在别处,并且有登录接口,就可以在这个自定义类中写相应的逻辑来实现。
这个类需要继承IResourceOwnerPasswordValidator接口,才能实现自定义登录。代码如下:
public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
{
public ResourceOwnerPasswordValidator()
{ } /// <summary>
/// Validates the resource owner password credential
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
await Task.Run(() =>
{
//在此处编写自己的账号密码验证逻辑,若验证通过,写入context的Result,告诉IdentityServer4账号密码是合法的,否则,不添加。
var userId = "";
context.Result = new GrantValidationResult(userId, OidcConstants.AuthenticationMethods.Password, DateTime.UtcNow);
});
}
}
创建完成后,我们的IdentityServer文件夹里有三个类:IdentityServerClients.cs,IdentityServerResources.cs,ResourceOwnerPasswordValidator.cs。
在IdentityServer4中还有其他功能可供使用,根据项目实际需求,可以集中放到这个文件夹内。
10,在Startup.cs文件中,引入IdentityServer4服务、配置JWT,以及告诉我们项目允许IdentityServer开始拦截路由并处理请求。
10.1,在ConfigureServices() 中引入IdentityServer4服务。在这里配置IdentityServer的测试用户,或者是自定义用户登录。
当同时设置了测试用户和自定义用户登录,那么IdentityServer是按照测试用户为主的。
services.AddIdentityServer()//Ids4服务
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(IdentityServerResources.GetApiResources())
.AddInMemoryIdentityResources(IdentityServerResources.GetIdentityResources())
.AddInMemoryClients(IdentityServerClients.GetClients())//把配置文件的Client配置资源放到内存
//.AddResourceOwnerValidator<ResourceOwnerPasswordValidator>()//自定义用户登录。即自定义用户登录又添加测试用户,则以测试用户为准
.AddTestUsers(IdentityServerClients.GetTestUsers())//添加测试用户
;
10.2,在ConfigureServices() 中配置JWT服务
//重写JWT,如果不配置JWT,那么IdentityServer4会在未认证身份的时候重定向到Account/Login,从而出错
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = Configuration["JWT:Authority"];
options.RequireHttpsMetadata = false;
options.Audience = "WebAppAPI";
options.TokenValidationParameters.ClockSkew = TimeSpan.FromMinutes();
options.TokenValidationParameters.RequireExpirationTime = true;
});
10.3,在Configure() 方法中添加以下内容以将IdentityServer中间件添加到HTTP管道
app.UseCors("default");
//允许IdentityServer开始拦截路由并处理请求。
app.UseIdentityServer();
//添加身份验证UseMvc
app.UseAuthentication();
10.4,在appsettings.json中加入JWT服务地址,以告诉IdentityServer去哪里寻找JWT服务,端口与我们在第5步,创建WebAPPHost时一致,appsettings.json文件代码如下
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"JWT": {
"Authority": "http://localhost:5002"
},
"AllowedHosts": "*"
}
11,改造我们的Controller,增加身份认证。
11.1,创建一个基类控制器:AuthorizeController.cs,控制器中暂时没有内容,只加入一个身份验证的类标签:[Authorize],代码如下
[Authorize]
public class AuthorizeController : Controller
{ }
当以后需要在所有控制器中做公共的事情,就可以在这个控制器中增加逻辑代码。
11.2,IdentityServer4身份认证已结束,我们把HomeController当做一个测试控制器,修改一下用于测试:
public class HomeController : AuthorizeController
{
[HttpGet]
public string Index()
{
var result = "{\"detail\":\"Hello Word!\"}";
return result;
}
}
12,运行起来,获取token的地址是:http://localhost:5002/connect/token,这是一个标准的获取token接口,无论域名时什么,地址是不变的。
body提交的参数分别是:
grant_type:password
username:admin001
password:111111
scope:WebAppAPI
client_id:client
client_secret:D7896FC26CAC97942DEF0402322524BB
然后,我们用获取到的token访问home/index接口
若不加token访问是被拦截的,返回401:
ASP.NET Core的无状态身份认证框架IdentityServer4的更多相关文章
- ASP.NET Core系列:JWT身份认证
1. JWT概述 JSON Web Token(JWT)是目前流行的跨域身份验证解决方案. JWT的官网地址:https://jwt.io JWT的实现方式是将用户信息存储在客户端,服务端不进行保存. ...
- ASP.NET CORE中使用Cookie身份认证
大家在使用ASP.NET的时候一定都用过FormsAuthentication做登录用户的身份认证,FormsAuthentication的核心就是Cookie,ASP.NET会将用户名存储在Cook ...
- 关于ASP.Net Core Web及API身份认证的解决方案
6月15日,在端午节前的最后一个工作日,想起有段日子没有写过文章了,倒有些荒疏了.今借夏日蒸蒸之气,偷得浮生半日悠闲.闲话就说到这里吧,提前祝大家端午愉快(屈原听了该不高兴了:))!.NetCore自 ...
- 理解ASP.NET Core - 基于Cookie的身份认证(Authentication)
注:本文隶属于<理解ASP.NET Core>系列文章,请查看置顶博客或点击此处查看全文目录 概述 通常,身份认证(Authentication)和授权(Authorization)都会放 ...
- ASP.NET Core如何使用WSFederation身份认证集成ADFS
如果要在ASP.NET Core项目中使用WSFederation身份认证,首先需要在项目中引入NuGet包: Microsoft.AspNetCore.Authentication.WsFedera ...
- ASP.NET Core编程实现基本身份认证
概览 在HTTP中,基本认证(Basic access authentication,简称BA认证)是一种用来允许网页浏览器或其他客户端程序在请求资源时提供用户名和口令形式的身份凭证的一种登录验证方式 ...
- 理解ASP.NET Core - 基于JwtBearer的身份认证(Authentication)
注:本文隶属于<理解ASP.NET Core>系列文章,请查看置顶博客或点击此处查看全文目录 在开始之前,如果你还不了解基于Cookie的身份认证,那么建议你先阅读<基于Cookie ...
- ASP.NET Core的身份认证框架IdentityServer4(7)- 使用客户端证书控制API访问
前言 今天(2017-9-8,写于9.8,今天才发布)一口气连续把最后几篇IdentityServer4相关理论全部翻译完了,终于可以进入写代码的过程了,比较累.目前官方的文档和Demo以及一些相关组 ...
- ASP.NET Core的身份认证框架IdentityServer4(6)- 开始
安装和概述 启动一个新的IdentityServer项目有两种基本方法: 从头开始 从Visual Studio中的ASP.NET身份模板开始 如果从头开始,我们提供了一些文档.项目帮助和内存存储支持 ...
随机推荐
- js 数组去重总结
es6 set ES6 提供了新的数据结构 Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. let arr = [1,2,3,4,3,2,3,4,6,7,6]; let unique = ...
- java包装类和值类型的关系
java包装类总是让人疑惑 它与值类型到底是怎么样一种关系? 本文将以int和Integer为例来探讨它们的关系 java值类型有int short char boolean byte long fl ...
- 设计模式之(十二)享元模式(Flyweight)
享元模式思想 就以小时候导锅来说吧(导锅是我家乡的方言,就是用细沙把一个模型锅的形状拓下来,然后把铝水倒进模型中,就导好一个锅了.小时候很喜欢看的,可惜现在看不到了.上个图片回忆下)了解了这个过程后就 ...
- vim 如何复制文件中多行到另一个文件
1.打开文件 vim a.txt b.tx 或者 vim *.txt 2.文件间切换 :n 切换到下一个文件 :wn 保存再切换 :N 到上一个文件 :wN 保存再切换 :.= 看当前行 3.假定当前 ...
- 渗透技巧——导出Chrome浏览器中保存的密码
0x00 前言 在后渗透阶段,获得权限后需要搜集目标系统的信息.信息越全面,越有助于进一步的渗透.对于Windows系统,用户浏览器往往包含有价值的信息. 在之前的文章<本地密码查看工具LaZa ...
- 微信小程序开发--常用开发实例
一.常用商品列表的换行排布 <view class="box_max"> <view class="box_min">限时秒杀</ ...
- k8s控制器资源(五)
Pod pod在之前说过,pod是kubernetes集群中是最小的调度单元,pod中可以运行多个容器,而node又可以包含多个pod,关系如下图: 在对pod的用法进行说明之前,有必要先对docke ...
- 10年前错过比特币,如今有斯坦福区块链项目pi币,对标btc,手机免费挖矿详细教程。
这一个斯坦福几个博士创业者做一个项目,目前还处于早期阶段,除了每天点一下挖矿之外,貌似不需要其他的操作,不需要耗费流量资源和手机大量的运算能力,就是一个安静的App而已....国内目前知道的人还不太多 ...
- centos自动同步服务器时间
原文:https://my.oschina.net/yysue/blog/1628733 1.安装ntpdate yum install ntpdate -y 2.测试是否正常 ntpdate cn. ...
- centos7.2下安装python3.6.5
yum groupinstall 'Development Tools' 出现错误 系统 centos 7.3 使用命令 yum groupinstall 'Development Tools' 出现 ...