title | date | tags |
---|---|---|
Asp.Net MVC接入Identity Server4 全记录 |
2019-09-20 10:40 |
Asp.Net MVC Identity Server |
-
Net Core 2.2+ //建议使用Net Core 3.0
-
Asp.Net Framework 4.6.2+
-
Visual Studio 2019//如果使用Net Core 3.0,你可能需要预览版
- 打开命令行。执行
dotnet new sln -n SsoTest
建立空白解决方案。
-
打开命令行或者powershell
# 新增IdentityServer4模板 dotnet new -i IdentityServer4.Templates # 新建项目 dotnet new is4empty -n IdentityServer # 添加到解决方案 dotnet sln add .\IdentityServer\IdentityServer.csproj # 进入项目目录 cd IdentityServer # 添加UI dotnet new is4ui
-
修改Config.cs文件
using IdentityServer4; using IdentityServer4.Models; using IdentityServer4.Test; using System.Collections.Generic; using System.Security.Claims;https://github.com/xyfy/UseMvc5ConnectIdentity4/blob/master/readme.md namespace IdentityServer { public static class Config { public static IEnumerable<IdentityResource> GetIdentityResources() { return new IdentityResource[] { new IdentityResources.OpenId(), new IdentityResources.Profile(), new IdentityResources.Email(), new IdentityResources.Phone(), }; } public static List<TestUser> GetUsers() { return new List<TestUser> { new TestUser { SubjectId = "1", Username = "alice", Password = "password", Claims = new [] { new Claim("name", "Alice"), new Claim("website", "https://alice.com") } }, new TestUser { SubjectId = "2", Username = "bob", Password = "password", Claims = new [] { new Claim("name", "Bob"), new Claim("website", "https://bob.com") } } }; } public static IEnumerable<ApiResource> GetApis() { return new ApiResource[] { new ApiResource ("api1", "My API") }; } public static IEnumerable<Client> GetClients() { var secret = "49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".Sha256(); return new Client[] { new Client { ClientId = "mvc", ClientName = "MVC Client", ClientSecrets = { new Secret (secret) }, AllowedGrantTypes = GrantTypes.HybridAndClientCredentials, // where to redirect to after login RedirectUris = { "http://localhost:5001/signin-oidc" }, // where to redirect to after logout PostLogoutRedirectUris = { "http://localhost:5001/signout-callback-oidc" }, AllowedScopes = new List<string> { IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Email, IdentityServerConstants.StandardScopes.Phone, IdentityServerConstants.StandardScopes.Profile, "api1" } }}; } } }
-
修改Startup.cs,取消注释
public IHostingEnvironment Environment { get; } public Startup(IHostingEnvironment environment) { Environment = environment; } public void ConfigureServices(IServiceCollection services) { // uncomment, if you want to add an MVC-based UI services.AddMvc().SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_2_1); var builder = services.AddIdentityServer() .AddInMemoryIdentityResources(Config.GetIdentityResources()) .AddInMemoryApiResources(Config.GetApis()) .AddInMemoryClients(Config.GetClients()) .AddTestUsers(Config.GetUsers()); if (Environment.IsDevelopment()) { builder.AddDeveloperSigningCredential(); } else { throw new Exception("need to configure key material"); } } public void Configure(IApplicationBuilder app) { if (Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } // uncomment if you want to support static files app.UseStaticFiles(); app.UseIdentityServer(); // uncomment, if you want to add an MVC-based UI app.UseMvcWithDefaultRoute(); }
-
新开一个命令行或者powershell窗口,运行服务端
# 还原nuget,编译 dotnet restore dotnet build # 运行 dotnet run
-
Install-Package IdentityModel -Version 3.10.10 Install-Package Microsoft.Owin.Security.Cookies Install-Package Microsoft.Owin.Security.OpenIdConnect Install-Package Microsoft.Owin.Host.SystemWeb
-
修改为Startup.cs文件.
using System; using System.Net.Http; using System.Security.Claims; using System.Web.Helpers; using IdentityModel; using IdentityModel.Client; using Microsoft.Owin; using Microsoft.Owin.Security; using Microsoft.Owin.Security.Cookies; using Microsoft.Owin.Security.OpenIdConnect; using Owin; [assembly: OwinStartup(typeof(SSOTest.Client.Startup))] namespace SSOTest.Client { public partial class Startup { public void Configuration(IAppBuilder app) { ConfigureAuth(app); } public void ConfigureAuth(IAppBuilder app) { AntiForgeryConfig.UniqueClaimTypeIdentifier = "sub"; app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = CookieAuthenticationDefaults.AuthenticationType, CookieHttpOnly = true }); var secret = "49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".ToSha256(); app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions { Authority = "http://localhost:5000", ClientId = "mvc", ClientSecret = secret, RedirectUri = "http://localhost:5001/signin-oidc", PostLogoutRedirectUri = "http://localhost:5001/signout-oidc", ResponseType = "code id_token", Scope = "openid profile", RequireHttpsMetadata = false, SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType, Notifications = new OpenIdConnectAuthenticationNotifications { AuthorizationCodeReceived = async n => { var client = new HttpClient(); var disco = await client.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest() { Address = "http://localhost:5000", Policy ={ RequireHttps = false } }); if (disco.IsError) throw new Exception(disco.Error); // use the code to get the access and refresh token var tokenResponse = await client.RequestAuthorizationCodeTokenAsync(new AuthorizationCodeTokenRequest() { Address = disco.TokenEndpoint, ClientId = "mvc", ClientSecret = "49C1A7E1-0C79-4A89-A3D6-A37998FB86B0", Code = n.Code, RedirectUri = n.RedirectUri }); if (tokenResponse.IsError) { throw new Exception(tokenResponse.Error); } // use the access token to retrieve claims from userinfo var userInfoResponse = await client.GetUserInfoAsync(new UserInfoRequest() { Address = disco.UserInfoEndpoint, Token = tokenResponse.AccessToken }); // create new identity var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType); id.AddClaims(userInfoResponse.Claims); id.AddClaim(new Claim("access_token", tokenResponse.AccessToken)); id.AddClaim(new Claim("expires_at", DateTime.UtcNow.AddSeconds(tokenResponse.ExpiresIn).ToString())); //id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken)); id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken)); id.AddClaim(new Claim("sid", n.AuthenticationTicket.Identity.FindFirst("sid").Value)); n.AuthenticationTicket = new AuthenticationTicket( new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType, "name", "role"), n.AuthenticationTicket.Properties); //TODO 本地USER同步 foreach (var item in userInfoResponse.Claims) { if (item.Type == "sub") { } } } } }); } } }
-
打开Controllers/HomeController.cs 在
About
这个Action上加特性[Authorize]
-
运行Client项目,访问 http://localhost:5001/Home/About