上节以对话形式,大概说了几种客户端授权模式的原理,这节重点介绍Hybrid模式在MVC下的使用。且为实现IdentityServer4从数据库获取User进行验证,并对Claim进行权限设置打下基础(第五节介绍)。

本节内容比较多,且涉及一、二节的内容,如有不懂,可先熟悉一、二节知识。


一、新建授权服务,命名为AuthServer

(1)新建Web API项目,不用配置HTTPS,不进行身份验证。

设置成控制台方式运行,端口设为5000。

       安装IdentityServer4

在Config.cs类中,添加如下代码:

public class Config
{ public static List<TestUser> GetUsers()
{
return new List<TestUser>
{
new TestUser
{
SubjectId = "",
Username = "test",
Password = "", Claims = new List<Claim>
{
new Claim("role", "user")
}
},
new TestUser
{
SubjectId = "",
Username = "admin",
Password = "", Claims = new List<Claim>
{
new Claim("role", "admin")
}
}
};
} public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
//new IdentityResource("roles","role",new List<string>{ "role"})
};
} public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("api1", "My API")
//new ApiResource("api1", "My API",new List<string>(){ "role"})
};
} // clients want to access resources (aka scopes)
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientId = "AuthServer",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes = { "api1" },
Claims= new List<Claim>(){new Claim("role","AuthServer") },
ClientClaimsPrefix = ""
},
// OpenID Connect implicit flow client (MVC)
new Client
{
ClientId = "mvc",
ClientName = "MVC Client",
AllowedGrantTypes = GrantTypes.Hybrid,
ClientSecrets =
{
new Secret("secret".Sha256())
},
// where to redirect to after login
RedirectUris = { "http://localhost:5002/signin-oidc" }, // where to redirect to after logout
PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" }, AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
//"roles"
}
}
};
}
}

这里IdentityResource映射于那些关于用户信息的scope, ApiResource映射于API资源的scopes。

(2)打开Startup.cs,在ConfigureServices里面调用AddIdentityServer来把Identity Server注册到ASP.NET Core的容器里面;随后我调用了AddDeveloperSigningCredentials方法,它会创建一个用于对token签名的临时密钥材料(但是在生产环境中应该使用可持久的密钥材料)

 public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(); services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddTestUsers(Config.GetUsers())
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients());
}

(3)打开Configure方法,把IdentityServer添加到ASP.NET Core的管道里。

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseIdentityServer();
//MVC配置
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}

(4)然后下载登录用的UI: https://github.com/IdentityServer/IdentityServer4.Quickstart.UI

把图中三个文件复制到AuthServer项目目录下。

复制完后项目如下:


二、新建MVC客户端,命名为MvcClient

(1)设置端口为5002。

修改Start.cs的ConfigureServices方法为:

public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
}); services.AddMvc(); JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies", options =>
{
//无权限,显示的页面
options.AccessDeniedPath = "/Authorization/AccessDenied";
})
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies"; options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false; options.ClientId = "mvc";
options.ResponseType = "code id_token";
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
//options.Scope.Add("roles"); options.SaveTokens = true;
options.ClientSecret = "secret";
options.GetClaimsFromUserInfoEndpoint = true; //options.ClaimActions.MapUniqueJsonKey("role", "role"); //options.TokenValidationParameters = new TokenValidationParameters
//{
// NameClaimType = JwtClaimTypes.GivenName,
// RoleClaimType = JwtClaimTypes.Role
//};
});
}

AddAuthentication方法来添加和配置身份认证中间件。这里使用Cookie作为验证用户的首选方式,而DefaultScheme = "Cookies",这个"Cookies"字符串是可以任意填写的,只要与后边的一致即可。但是如果同一个服务器上有很多应用的话,这个Scheme的名字不能重复。

DefaultChanllangeScheme设为"oidc", 这个名字与后边配置OpenIdConnect的名字要一样. 当用户需要登陆的时候, 将使用的是OpenId Connect Scheme。

AddCookie其参数是之前配置的DefaultScheme名称,这配置了Cookie的处理者,并让应用程序为我们的DefaultScheme启用了基于Cookie的身份认证。一旦ID Token验证成功并且转化为Claims身份标识后,这些信息就将会保存于被加密的Cookie里。

AddOpenIdConnect方法添加了对OpenID Connect流程的支持,它让配置了用来执行OpenId Connect 协议的处理者。这个处理者会负责创建身份认证请求,Token请求和其它请求,并负责ID Token的验证工作。它的身份认证scheme就是之前配置的"oidc",它的意思就是如果该客户端的某部分要求身份认证的时候,OpenID Connect将会作为默认方案被触发(因为之前设置的DefaultChallengeScheme是"oidc", 和这里的名字一样)。

SignInScheme和上面的DefaultScheme一致,它保证身份认证成功的结果将会被保存在方案名为"Cookies"的Cookie里。

Authority就是Identity Provider的地址。

ClientId和Secret要与IdentityProvider里面的值一样。

请求的Scope有openid和profile,其实中间件默认也包括了这些scope,但是写出来更明确一些。

SaveTokens=true,表示允许存储从Identity Provider那里获得的tokens。

(2)修改Configure方法为:

 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
} app.UseAuthentication(); app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}

(3)然后对HomeController加上身份验证。[Authorize]

(4)再修改About的页面,显示User的Claim信息。

@{
ViewData["Title"] = "About";
}
<h2>@ViewData["Title"]</h2> @*<dt>Access Token</dt>
<dd>@ViewData["AccessToken"]</dd>*@ <dl>
@foreach (var claim in User.Claims)
{
<dt>@claim.Type</dt>
<dd>@claim.Value</dd>
}
</dl>

(5)现在,可以运行AuthServer和MvcClient项目了。

(6)输入Config文件中的TestUser的用户,密码都设为123,点击Login

允许授权

查看About页面,显示了user相关的claim信息。

(7)当然,登出功能还没实现,这里先实现登出。打开图中cshtml文件

添加如下代码:

 @if (User.Identity.IsAuthenticated)
{
<li><a asp-area="" asp-controller="Home" asp-action="Logout">Logout</a></li>
}

然后在HomeController控制器中添加Logout方法

public async Task Logout()

{

await HttpContext.SignOutAsync("Cookies");

await HttpContext.SignOutAsync("oidc");

}

首先要清除本地的Cookie,这个Cookie的名字要与之前配置的默认方案里的名字一致,这一步就相当于登出MVC客户端。

后一行代码的作用是跳转回到Identity Provider,然后用户可以继续登出IDP, 也就是IDP会清除它的Cookie。

(8)接着在AuthServer中的Quickstart/Account/AccountOptions实现自动跳转回登录页面。

好了,登录登出实现完了,我们接着实现Claim权限限制。


三、为MVC客户端设置Claim身份验证

(1)添加TestUser的Claim中Type为role

(2)定义用户信息scope的role信息

第一个参数是scope的名字,第二个参数是scope的显示名,第三个参数是它所包含的claim类型,这里就是“role”。

(3)然后还需要客户端允许请求“roles”这个scope

(4)MVC客户端的配置,打开MVC的startup,添加“roles”这个scope:options.Scope.Add("roles");

把role claim 映射到User.Claims里:options.ClaimActions.MapUniqueJsonKey("role", "role");

role claim映射成ASP.NET Core MVC可以识别的角色Roles。

options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = JwtClaimTypes.GivenName,
RoleClaimType = JwtClaimTypes.Role
};

这样MVC中的role就可以识别User.Claims的role了。

(6)最后在MvcClient项目HomeController中   About前,加上role为admin身份验证。[Authorize(Roles ="admin")]

然后运行,先用test账号登录进行验证。

发现点About页面没有权限进不去

然后登出,换admin账号登录

User.Claims的role成功被MVC中角色role识别,展示About页面。


这节主要介绍Hybrid在MVC下的使用,包括User的登录登出和Claim对MVC的身份授权。

然而,这只是针对内存用户TestUser进行操作的,显示实际项目中不能满足我们需求。下节将在本节的基础上介绍如何实现IdentityServer4从数据库获取User进行验证并对Claim进行身份验证。

参考博客: https://www.cnblogs.com/cgzl/p/9268371.html

源码地址:https://github.com/Bingjian-Zhu/Mvc-HybridFlowV0.git

IdentityServer4-MVC+Hybrid实现Claims授权验证(四)的更多相关文章

  1. Angular SPA基于Ocelot API网关与IdentityServer4的身份认证与授权(四)

    在上一讲中,我们已经完成了一个完整的案例,在这个案例中,我们可以通过Angular单页面应用(SPA)进行登录,然后通过后端的Ocelot API网关整合IdentityServer4完成身份认证.在 ...

  2. asp.net mvc 使用AuthorizeAttribute做授权验证

    授权验证,比如登陆验证 1.自定义属性继承AuthorizeAttribute 2.重写OnAuthorization方法 3.通过AllowAnonymousAttribute特性处理无需授权的Ac ...

  3. ASP.NET CORE API Swagger+IdentityServer4授权验证

    简介 本来不想写这篇博文,但在网上找到的文章博客都没有完整配置信息,所以这里记录下. 不了解IdentityServer4的可以看看我之前写的入门博文 Swagger 官方演示地址 源码地址 配置Id ...

  4. 【从零开始搭建自己的.NET Core Api框架】(四)实战!带你半个小时实现接口的JWT授权验证

    系列目录 一.  创建项目并集成swagger 1.1 创建 1.2 完善 二. 搭建项目整体架构 三. 集成轻量级ORM框架——SqlSugar 3.1 搭建环境 3.2 实战篇:利用SqlSuga ...

  5. ASP.NET MVC WebApi接口授权验证

    对于很任何多开发者来说,不管是使用任何一种框架,或者是使用任何一种语言,都要使用面向接口编程.使用面向接口编程的时候,那么就会有很多的权限验证,用户验证等等. 特别是对于一些系统来说,别人想要对接你的 ...

  6. ASP.NET MVC Model验证(四)

    ASP.NET MVC Model验证(四) 前言 本篇主要讲解ModelValidatorProvider 和ModelValidator两种类型的自定义实现,前者是Model验证提供程序,而Mod ...

  7. 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 二十四║ Vuex + JWT 实现授权验证登录

    壹周回顾 哈喽,又是元气满满的一个周一,又与大家见面了,周末就是团圆节了,正好咱们的前后端也要团圆了,为什么这么说呢,因为以后的开发可能就需要前后端一起了,两边也终于会师了,还有几天Vue系列就基本告 ...

  8. IdentityServer4-从数据库获取User进行授权验证(五)

    本节将在第四节基础上介绍如何实现IdentityServer4从数据库获取User进行验证,并对Claim进行权限设置. 一.新建Web API资源服务,命名为ResourceAPI (1)新建API ...

  9. 用Middleware给ASP.NET Core Web API添加自己的授权验证

    Web API,是一个能让前后端分离.解放前后端生产力的好东西.不过大部分公司应该都没能做到完全的前后端分离.API的实现方式有很 多,可以用ASP.NET Core.也可以用ASP.NET Web ...

随机推荐

  1. 基于神经网络的颜色恒常性—Fully Convolutional Color Constancy with Confidence-weighted Pooling

    论文地址: http://openaccess.thecvf.com/content_cvpr_2017/papers/Hu_FC4_Fully_Convolutional_CVPR_2017_pap ...

  2. 【逆向知识】VS程序反汇编找main函数

    工具:OllyICE 调试快捷键说明: F2键:设置断点,只要在光标定位的位置 F4键:程序运行到光标处 F7键:单步步入.功能同单步步过(F8)类似,区别是遇到 CALL 等子程序时会进入其中,进入 ...

  3. 【转】Python数据类型之“数字(numerics)”

    [转]Python数据类型之“数字(numerics)” 上一节内容说的是“Python基本语法”,本节主要讲下Python中的数据类型. 存储在内存中的数据通常有两个属性: 在内存中的存放位置:这个 ...

  4. Python startswith() 函数 判断字符串开头

    Python startswith() 函数 判断字符串开头 函数:startswith() 作用:判断字符串是否以指定字符或子字符串开头 一.函数说明语法:string.startswith(str ...

  5. Linux中THIS_MODULE宏定义详解

    一直都在耿耿于怀,这个THIS_MODULE到底是个什么玩意,linux内核中无处不在的东西.今天上网搜了一下,算是基本明白了.网上牛人写的已经比较详细,另外目前暂时没有时间往更深层次分析,所以直接贴 ...

  6. 所有Windows7下游戏的全屏问题

    Win键+R键,打开运行窗口,输入regedit 回车,这样就打开了注册表编辑器,然后,定位到以下位置:HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\ ...

  7. Mashup

    简介 mashup是糅合,是当今网络上新出现的一种网络现象,将两种以上使用公共或者私有数据库的web应用,加在一起,形成一个整合应用.一般使用源应用的API接口,或者是一些rss输出(含atom)作为 ...

  8. 无向图最小割Stoer-Wagner算法学习

    无向连通网络,去掉一个边集可以使其变成两个连通分量则这个边集就是割集,最小割集当然就权和最小的割集. 使用最小切割最大流定理: 1.min=MAXINT,确定一个源点 2.枚举汇点 3.计算最大流,并 ...

  9. Cookie/Session机制详解(转载)

    原文链接:http://blog.csdn.net/fangaoxin/article/details/6952954 会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话.常用 ...

  10. zookeeper3.4.6配置实现自动清理日志

    在使用zookeeper过程中,我们知道,会有dataDir和dataLogDir两个目录,分别用于snapshot和事务日志的输出(默认情况下只有dataDir目录,snapshot和事务日志都保存 ...