一、WebForms集成OAuth认证:
1、新建webform项目
2、添加Startup.cs文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
using System; using System.Threading.Tasks; using Microsoft.Owin; using Microsoft.Owin.Extensions; using Owin; using System.IdentityModel.Tokens; using Microsoft.Owin.Security.Cookies; using Microsoft.Owin.Security.OpenIdConnect; using System.Linq; using System.Security.Claims; using IdentityModel.Client; using Microsoft.IdentityModel.Protocols; [assembly: OwinStartup(typeof(WebFormOwin.Startup))] namespace WebFormOwin { public class Startup { public void Configuration(IAppBuilder app) { app.UseCookieAuthentication(new CookieAuthenticationOptions() { AuthenticationType = "Cookies", ExpireTimeSpan = TimeSpan.FromMinutes(10), SlidingExpiration = true }); //JwtSecurityTokenHandler.InboundClaimTypeMap.Clear(); app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions { AuthenticationType = "oidc", SignInAsAuthenticationType = "Cookies", Authority = "https://auth-dev.veima.com", ClientId = "xiaomage", RedirectUri = "http://localhost:5000/", PostLogoutRedirectUri = "http://localhost:5000/", ResponseType = "id_token token", Scope = "openid profile", UseTokenLifetime = false, Notifications = new OpenIdConnectAuthenticationNotifications { SecurityTokenValidated = async n => { var claims_to_exclude = new[] { "aud", "iss", "nbf", "exp", "nonce", "iat", "at_hash" }; var claims_to_keep = n.AuthenticationTicket.Identity.Claims .Where(x => false == claims_to_exclude.Contains(x.Type)).ToList(); claims_to_keep.Add(new Claim("id_token", n.ProtocolMessage.IdToken)); if (n.ProtocolMessage.AccessToken != null) { claims_to_keep.Add(new Claim("access_token", n.ProtocolMessage.AccessToken)); var userInfoClient = new UserInfoClient(new Uri("https://auth-dev.veima.com/connect/userinfo"), n.ProtocolMessage.AccessToken); var userInfoResponse = await userInfoClient.GetAsync(); var userInfoClaims = userInfoResponse.Claims .Where(x => x.Item1 != "sub") // filter sub since we're already getting it from id_token .Select(x => new Claim(x.Item1, x.Item2)); claims_to_keep.AddRange(userInfoClaims); } var ci = new ClaimsIdentity( n.AuthenticationTicket.Identity.AuthenticationType, "name", "role"); ci.AddClaims(claims_to_keep); n.AuthenticationTicket = new Microsoft.Owin.Security.AuthenticationTicket( ci, n.AuthenticationTicket.Properties ); }, RedirectToIdentityProvider = n => { if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest) { var id_token = n.OwinContext.Authentication.User.FindFirst("id_token")?.Value; n.ProtocolMessage.IdTokenHint = id_token; } return Task.FromResult(0); } } }); app.UseStageMarker(PipelineStage.Authenticate); } } }
3、添加引用类库dll
4、配置文件web.config中添加代码
assemblyBinding节点下:
<dependentAssembly> <assemblyIdentity name="System.IdentityModel.Tokens.Jwt" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-4.0.20622.1351" newVersion="4.0.20622.1351" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.IdentityModel.Protocol.Extensions" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-1.0.2.33" newVersion="1.0.2.33" /> </dependentAssembly>
configuration节点下:
<location path="About"> <system.web> <authorization> <deny users="?" /> </authorization> </system.web> </location>
二、MVC集成OAuth认证:
1、新建mvc项目
2、添加Startup.cs文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
using IdentityModel.Client; using Microsoft.IdentityModel.Protocols; using Microsoft.Owin; using Microsoft.Owin.Extensions; using Microsoft.Owin.Security; using Microsoft.Owin.Security.Cookies; using Microsoft.Owin.Security.OpenIdConnect; using Owin; using System; using System.Collections.Generic; using System.IdentityModel.Tokens; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; [assembly: OwinStartup(typeof(MvcOwin.Startup))] namespace MvcOwin { public class Startup { //public void Configuration(IAppBuilder app) //{ // //JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>(); // app.UseCookieAuthentication(new CookieAuthenticationOptions // { // AuthenticationType = "Cookies" // }); // app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions // { // Authority = "https://auth-dev.veima.com", // ClientId = "xiaomage", // RedirectUri = "http://localhost:5000/", // PostLogoutRedirectUri = "http://localhost:5000/", // ResponseType = "id_token token", // Scope = "openid profile", // UseTokenLifetime = false, // SignInAsAuthenticationType = "Cookies", // }); //} public void Configuration(IAppBuilder app) { app.UseCookieAuthentication(new CookieAuthenticationOptions() { AuthenticationType = "Cookies", ExpireTimeSpan = TimeSpan.FromMinutes(10), SlidingExpiration = true }); //JwtSecurityTokenHandler.InboundClaimTypeMap.Clear(); app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions { AuthenticationType = "oidc", SignInAsAuthenticationType = "Cookies", Authority = "https://auth-dev.veima.com", ClientId = "xiaomage", RedirectUri = "http://localhost:5000/",//http://localhost:5000/ PostLogoutRedirectUri = "http://localhost:5000/", ResponseType = "id_token token", Scope = "openid profile", UseTokenLifetime = false, Notifications = new OpenIdConnectAuthenticationNotifications { SecurityTokenValidated = async n => { var claims_to_exclude = new[] { "aud", "iss", "nbf", "exp", "nonce", "iat", "at_hash" }; var claims_to_keep = n.AuthenticationTicket.Identity.Claims .Where(x => false == claims_to_exclude.Contains(x.Type)).ToList(); claims_to_keep.Add(new Claim("id_token", n.ProtocolMessage.IdToken)); if (n.ProtocolMessage.AccessToken != null) { claims_to_keep.Add(new Claim("access_token", n.ProtocolMessage.AccessToken)); var userInfoClient = new UserInfoClient(new Uri("https://auth-dev.veima.com/connect/userinfo"), n.ProtocolMessage.AccessToken); var userInfoResponse = await userInfoClient.GetAsync(); var userInfoClaims = userInfoResponse.Claims .Where(x => x.Item1 != "sub") // filter sub since we're already getting it from id_token .Select(x => new Claim(x.Item1, x.Item2)); claims_to_keep.AddRange(userInfoClaims); } var ci = new ClaimsIdentity( n.AuthenticationTicket.Identity.AuthenticationType, "name", "role"); ci.AddClaims(claims_to_keep); n.AuthenticationTicket = new Microsoft.Owin.Security.AuthenticationTicket( ci, n.AuthenticationTicket.Properties ); }, RedirectToIdentityProvider = n => { if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest) { var id_token = n.OwinContext.Authentication.User.FindFirst("id_token")?.Value; n.ProtocolMessage.IdTokenHint = id_token; } return Task.FromResult(0); } } }); app.UseStageMarker(PipelineStage.Authenticate); } } }
3、配置文件Web.config中assemblyBinding节点下添加代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
<dependentAssembly> <assemblyIdentity name="Microsoft.IdentityModel.Protocol.Extensions" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-1.0.2.33" newVersion="1.0.2.33" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.IdentityModel.Tokens.Jwt" publicKeyToken="31bf3856ad364e35" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-4.0.20622.1351" newVersion="4.0.20622.1351"/> </dependentAssembly>
4、控制器添加特性
[Authorize] public ActionResult Claims() { ViewBag.Message = "Claims"; var cp = (ClaimsPrincipal)User; //ViewData["access_token"] = cp.FindFirst("access_token").Value; return View(); }
5、退出登录
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
public ActionResult Signout() { // also possible to pass post logout redirect url via properties //var properties = new AuthenticationProperties //{ // RedirectUri = "http://localhost:2672/" //}; Request.GetOwinContext().Authentication.SignOut(); //return RedirectToAction("Index", "Home"); return Redirect("/"); }
6、页面显示登录信息
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
<dl> @foreach (var claim in System.Security.Claims.ClaimsPrincipal.Current.Claims) { <dt> @claim.Type </dt> <dd> @claim.Value </dd> } </dl> <ul> @foreach (var claim in ((System.Security.Claims.ClaimsPrincipal)User).Claims) { <li>@claim.Type + ", " + @claim.Value </li> } </ul>
7、母版页显示注销按钮
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
@if (User.Identity.IsAuthenticated) { <li>@Html.ActionLink("Signout", "Signout", "Home")</li> }
二、.Net Core Web项目集成OAuth认证:
1、新建core Web项目
2、Startup.cs文件添加代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; namespace CoreWebOwin { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. 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().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); services.AddAuthentication(options => { options.DefaultScheme = "Cookies"; options.DefaultChallengeScheme = "oidc"; }) .AddCookie("Cookies") .AddOpenIdConnect("oidc", options => { options.SignInScheme = "Cookies"; options.Authority = "https://auth-dev.veima.com"; options.RequireHttpsMetadata = false; options.ClientId = "xiaomage"; options.SaveTokens = true; }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseCookiePolicy(); app.UseAuthentication(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); } } }
3、退出
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
public async Task Logout() { await HttpContext.SignOutAsync("Cookies"); await HttpContext.SignOutAsync("oidc"); }
4、页面显示登录信息
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
<dl> @foreach (var claim in User.Claims) { <dt>@claim.Type</dt> <dd>@claim.Value</dd> } </dl>
5、母版页显示注销按钮
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
@if (Context.User?.Identity?.IsAuthenticated ?? false) { <li><a asp-area="">@Context.User?.Claims.First(c => c.Type == "name").Value</a></li> <li><a asp-action="Logout" asp-controller="Home">注销</a></li> }
附:
官方实例:https://github.com/IdentityServer/IdentityServer3.Samples.git