相关知识点

不再对IdentityServer4做相关介绍,博客园上已经有人出了相关的系列文章,不了解的可以看一下:

蟋蟀大神的:小菜学习编程-IdentityServer4

晓晨Master:IdentityServer4

以及Identity,Claim等相关知识:

Savorboard: ASP.NET Core 之 Identity 入门(一),ASP.NET Core 之 Identity 入门(二)

创建IndentityServer4 服务

创建一个名为QuickstartIdentityServerASP.NET Core Web 空项目(asp.net core 2.0),端口5000

NuGet包:

修改Startup.cs 设置使用IdentityServer

public class Startup{public void ConfigureServices(IServiceCollection services){// configure identity server with in-memory stores, keys, clients and scopesservices.AddIdentityServer().AddDeveloperSigningCredential().AddInMemoryIdentityResources(Config.GetIdentityResourceResources()).AddInMemoryApiResources(Config.GetApiResources()).AddInMemoryClients(Config.GetClients()).AddResourceOwnerValidator<ResourceOwnerPasswordValidator>().AddProfileService<ProfileService>();}public void Configure(IApplicationBuilder app, IHostingEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseIdentityServer();}}

添加Config.cs配置IdentityResourceApiResource以及Client

 public class Config{public static IEnumerable<IdentityResource> GetIdentityResourceResources(){return new List<IdentityResource>{new IdentityResources.OpenId(), //必须要添加,否则报无效的scope错误new IdentityResources.Profile()};}// scopes define the API resources in your systempublic static IEnumerable<ApiResource> GetApiResources(){return new List<ApiResource>{new ApiResource("api1", "My API")};}// clients want to access resources (aka scopes)public static IEnumerable<Client> GetClients(){// client credentials clientreturn new List<Client>{new Client{ClientId = "client1",AllowedGrantTypes = GrantTypes.ClientCredentials,ClientSecrets ={new Secret("secret".Sha256())},AllowedScopes = { "api1",IdentityServerConstants.StandardScopes.OpenId, //必须要添加,否则报forbidden错误IdentityServerConstants.StandardScopes.Profile},},// resource owner password grant clientnew Client{ClientId = "client2",AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,ClientSecrets ={new Secret("secret".Sha256())},AllowedScopes = { "api1",IdentityServerConstants.StandardScopes.OpenId, //必须要添加,否则报forbidden错误IdentityServerConstants.StandardScopes.Profile }}};}}

因为要使用登录的时候要使用数据中保存的用户进行验证,要实IResourceOwnerPasswordValidator接口:

public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator{public ResourceOwnerPasswordValidator(){}public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context){//根据context.UserName和context.Password与数据库的数据做校验,判断是否合法if (context.UserName=="wjk"&&context.Password=="123"){context.Result = new GrantValidationResult(subject: context.UserName,authenticationMethod: "custom",claims: GetUserClaims());}else{//验证失败context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "invalid custom credential");}}//可以根据需要设置相应的Claimprivate Claim[] GetUserClaims(){return new Claim[]{new Claim("UserId", 1.ToString()),new Claim(JwtClaimTypes.Name,"wjk"),new Claim(JwtClaimTypes.GivenName, "jaycewu"),new Claim(JwtClaimTypes.FamilyName, "yyy"),new Claim(JwtClaimTypes.Email, "977865769@qq.com"),new Claim(JwtClaimTypes.Role,"admin")};}}

IdentityServer提供了接口访问用户信息,但是默认返回的数据只有sub,就是上面设置的subject: context.UserName,要返回更多的信息,需要实现IProfileService接口:

public class ProfileService : IProfileService{public async Task GetProfileDataAsync(ProfileDataRequestContext context){try{//depending on the scope accessing the user data.var claims = context.Subject.Claims.ToList();//set issued claims to returncontext.IssuedClaims = claims.ToList();}catch (Exception ex){//log your error}}public async Task IsActiveAsync(IsActiveContext context){context.IsActive = true;}

context.Subject.Claims就是之前实现IResourceOwnerPasswordValidator接口时claims: GetUserClaims()给到的数据。
另外,经过调试发现,显示执行ResourceOwnerPasswordValidator 里的ValidateAsync,然后执行ProfileService 里的IsActiveAsyncGetProfileDataAsync
启动项目,使用postman进行请求就可以获取到token

再用token获取相应的用户信息:

token认证服务一般是与web程序分开的,上面创建的QuickstartIdentityServer项目就相当于服务端,我们需要写业务逻辑的web程序就相当于客户端。当用户请求web程序的时候,web程序拿着用户已经登录取得的tokenIdentityServer服务端校验。

创建web应用

创建一个名为API的ASP.NET Core Web 空项目(asp.net core 2.0),端口5001
NuGet包:

修改Startup.cs 设置使用IdentityServer进行校验:

public class Startup{public void ConfigureServices(IServiceCollection services){services.AddMvcCore(option=>{option.Filters.Add(new TestAuthorizationFilter());}).AddAuthorization().AddJsonFormatters();services.AddAuthentication("Bearer").AddIdentityServerAuthentication(options =>{options.Authority = "http://localhost:5000";options.RequireHttpsMetadata = false;options.ApiName = "api1";});}public void Configure(IApplicationBuilder app){app.UseAuthentication();app.UseMvc();}}

创建IdentityController

[Route("[controller]")]public class IdentityController : ControllerBase{[HttpGet][Authorize]public IActionResult Get(){return new JsonResult("Hello Word");}}

分别运行QuickstartIdentityServer,API项目。用生成的token访问API:

通过上述程序,已经可以做一个前后端分离的登录功能。

实际上,web应用程序中我们经常需要获取当前用户的相关信息进行操作,比如记录用户的一些操作日志等。之前说过IdentityServer提供了接口/connect/userinfo来获取用户的相关信息。之前我的想法也是web程序中拿着token去请求这个接口来获取用户信息,并且第一次获取后做相应的缓冲。但是感觉有点怪怪的,IdentityServer不可能没有想到这一点,正常的做法应该是校验通过会将用户的信息返回的web程序中。问题又来了,如果IdentityServer真的是这么做的,web程序该怎么获取到呢,查了官方文档也没有找到。然后就拿着"Claim"关键字查了一通(之前没了解过ASP.NET Identity),最后通过HttpContext.User.Claims取到了设置的用户信息:

修改IdentityController

[Route("[controller]")]public class IdentityController : ControllerBase{[HttpGet][Authorize]public IActionResult Get(){return new JsonResult(from c in HttpContext.User.Claims select new { c.Type, c.Value });}}

权限控制

IdentityServer4 也提供了权限管理的功能,大概看了一眼,没有达到我想要(没耐心去研究)。
我需要的是针对不同的模块,功能定义权限码(字符串),每个权限码对应相应的功能权限。当用户进行请求的时候,判断用户是否具备相应功能的权限(是否赋予了相应的权限字符串编码),来达到权限控制。

IdentityServer的校验是通过Authorize特性来判断相应的ControllerAction是否需要校验。这里也通过自定义特性来实现权限的校验,并且是在原有的Authorize特性上进行扩展。可行的方案继承AuthorizeAttribute,重写。可是在.net core中提示没有OnAuthorization方法可进行重写。最后参考的ABP的做法,过滤器和特性共同使用。

新建TestAuthorizationFilter.cs

public class TestAuthorizationFilter : IAuthorizationFilter{public void OnAuthorization(AuthorizationFilterContext context){if (context.Filters.Any(item => item is IAllowAnonymousFilter)){return;}if (!(context.ActionDescriptor is ControllerActionDescriptor)){return;}var attributeList = new List<object>();attributeList.AddRange((context.ActionDescriptor as ControllerActionDescriptor).MethodInfo.GetCustomAttributes(true));attributeList.AddRange((context.ActionDescriptor as ControllerActionDescriptor).MethodInfo.DeclaringType.GetCustomAttributes(true));var authorizeAttributes = attributeList.OfType<TestAuthorizeAttribute>().ToList();var claims = context.HttpContext.User.Claims;// 从claims取出用户相关信息,到数据库中取得用户具备的权限码,与当前Controller或Action标识的权限码做比较var userPermissions = "User_Edit";if (!authorizeAttributes.Any(s => s.Permission.Equals(userPermissions))){context.Result = new JsonResult("没有权限");}return;}}

新建TestAuthorizeAttribute

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]public class TestAuthorizeAttribute: AuthorizeAttribute{public string Permission { get; set; }public TestAuthorizeAttribute(string permission){Permission = permission;}}

IdentityController [Authorize]改为[TestAuthorize("User_Edit")],再运行API项目。

通过修改权限码,验证是否起作用

除了使用过滤器和特性结合使用,貌似还有别的方法,有空再研究。

IdentityServer4实现Token登录以及权限控制相关推荐

  1. 手工搭建基于ABP的框架(3) - 登录,权限控制与日志

    为了防止不提供原网址的转载,特在这里加上原文链接: http://www.cnblogs.com/skabyy/p/7695258.html 本篇将实现登录.权限控制.日志配置与审计日志的功能.首先我 ...

  2. 传智健康_第9章 移动端开发-手机快速登录、权限控制

    传智健康_第9章 移动端开发-手机快速登录.权限控制 文章目录 传智健康_第9章 移动端开发-手机快速登录.权限控制 1. 需求分析 2. 手机快速登录 2.1 页面调整 2.1.1 发送验证码 2. ...

  3. IdentityServer4实战 - 基于角色的权限控制及Claim详解

    一.前言 大家好,许久没有更新博客了,最近从重庆来到了成都,换了个工作环境,前面都比较忙没有什么时间,这次趁着清明假期有时间,又可以分享一些知识给大家.在QQ群里有许多人都问过IdentityServ ...

  4. 使用service实现登录、权限控制

    2019独角兽企业重金招聘Python工程师标准>>> 文章来源:http://blog.ddlisting.com 官网对于登录.用户权限的介绍只有一段简单的说明,并没有详细说明如 ...

  5. Flask-Login Flask-Security 登录与权限控制

    先看官方例子: from flask import Flask, render_template from flask_sqlalchemy import SQLAlchemy from flask_ ...

  6. OAuth2.0 原理流程及其单点登录和权限控制

    作者:王克锋 kefeng.wang/2018/04/06/oauth2-sso 单点登录是多域名企业站点流行的登录方式.本文以现实生活场景辅助理解,力争彻底理清 OAuth2.0 实现单点登录的原理 ...

  7. 傻瓜式使用SpringSecurity完成前后端分离+JWT+登录认证+权限控制

    流程分析 流程说明: 客户端发起一个请求,进入 Security 过滤器链.当到 LogoutFilter 的时候判断是否是登出路径,如果是登出路径则到 logoutHandler ,如果登出成功则到 ...

  8. java oauth sso 源码_基于Spring Security Oauth2的SSO单点登录+JWT权限控制实践

    概 述 在前文<基于Spring Security和 JWT的权限系统设计>之中已经讨论过基于 Spring Security和 JWT的权限系统用法和实践,本文则进一步实践一下基于 Sp ...

  9. spring boot系列03--spring security (基于数据库)登录和权限控制(下)

    (接上篇) 后台 先说一下AuthConfig.java Spring Security的主要配置文件之一 AuthConfig 1 @Configuration 2 @EnableWebSecuri ...

最新文章

  1. python元组是数组吗,Python基础(4)——数组元组
  2. 新建sublime 的python代码文件时自动在头部增加几行常用代码
  3. java 创建web项目_java – Eclipse:以编程方式创建动态Web项目
  4. 你的代码可以是优雅的,但是还有更重要的
  5. 计算机考试用英语怎么说,“全国大学生计算机等级考试一级”英语怎么说?
  6. PHP距离春节还剩多少天,2019年春节倒计时 现在距离2019年春节还有多少天 - 中国万年历...
  7. Perl语言入门(05 文件)
  8. python计算正弦值_Python科学计算(二)——正弦信号的时域波形与频谱图
  9. java贪吃蛇_Java贪吃蛇游戏完善版
  10. 韦东山freeRTOS系列教程之【第三章】任务管理
  11. C# Color颜色RGB对照表
  12. 强网杯 2018 core ROP做法
  13. Python 制作个性化形状的云词
  14. 企业邮箱哪个最好用?企业内部邮箱多少钱? 企业邮箱安全怎么选择?
  15. uniapp swiper组件被内容撑开
  16. 5月17号软件资讯更新合集....
  17. 结构体中元素引用—— “.“ 与 “->“
  18. 【TCP网络编程】C语言实现TCP服务器和客户端之间的通信(linux)
  19. uniapp - 微信公众号授权登录
  20. 高铁、动车到底啥区别?看完彻底懂了

热门文章

  1. 1.Concurrent概述
  2. [Magento] Overriding Core files
  3. 广州大学城热水解锁卡dump
  4. Selenium2学习笔记
  5. 突然无法访问局域网内的共享文件夹
  6. 数据科学库(HM)(Day2)——matplotlib常用统计图
  7. 学习日记(1.12)
  8. 同一台服务器上安装mysql5.5和mysql5.7 不同版本的实例
  9. 英文演讲文稿 java,英文演讲稿优秀范文五篇
  10. 集合的打印、列表List、迭代器Iterators