一、IS4服務器配置
1、新建一個Asp.net Core MVC程序,模板選擇 Empty
2、Nuget添加 IdentityServer4,我這里添加的是2.5.3
3、添加Config文件,配置clients和scopes等信息,需要持久化配置的可以看 https://www.cnblogs.com/fengchao1000/p/10184921.html
public class Config { // scopes define the resources in your system public static IEnumerable<IdentityResource> GetIdentityResources() { return new List<IdentityResource> { new IdentityResources.OpenId(), new IdentityResources.Profile() }; } public static IEnumerable<ApiResource> GetApis() { return new List<ApiResource> { new ApiResource("FrameworkAPI",new List<string>(){JwtClaimTypes.Subject}) }; } public static IEnumerable<Client> GetClients() { return new List<Client> { //Implicit模式Client配置,適用於SPA new Client { ClientId = "Test", ClientName = "Test", AllowedGrantTypes = GrantTypes.Implicit, AllowAccessTokensViaBrowser = true, AccessTokenLifetime = 60*60, AccessTokenType = AccessTokenType.Jwt, RedirectUris = { "https://localhost:5003/signin-callback.html", "https://localhost:5003/silent-callback.html" }, PostLogoutRedirectUris = { "https://localhost:5003" }, AllowedCorsOrigins = { "https://localhost:5003" }, RequireConsent = false, AllowedScopes = { IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Profile, "FrameworkAPI"//對應webapi里面的scope配置 } }, //ResourceOwnerPassword模式Client配置,適用於App、winform new Client { ClientId = "App", ClientName = "App", ClientSecrets = { new Secret("123456".Sha256()) }, AccessTokenLifetime = 60*60,//單位s AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, SlidingRefreshTokenLifetime = 2592000, AllowOfflineAccess = true, AllowedScopes = new List<string> { "FrameworkAPI",//對應webapi里面的scope配置 StandardScopes.OfflineAccess, StandardScopes.OpenId, StandardScopes.Profile } } }; } }
4、添加ProfileService文件,用於自定義登錄返回信息
/// <summary> /// 自定義用戶登錄返回的信息claims /// </summary> public class ProfileService : IProfileService { private readonly ILogger logger; public ProfileService(ILogger<ProfileService> logger) { this.logger = logger; } public async Task GetProfileDataAsync(ProfileDataRequestContext context) { try { var claims = context.Subject.Claims.ToList(); context.IssuedClaims = claims.ToList(); } catch (Exception ex) { logger.LogError(ex.ToString()); } } public async Task IsActiveAsync(IsActiveContext context) { context.IsActive = true; } }
5、添加ResourceOwnerPasswordValidator文件,在ResourceOwnerPassword模式下用於自定義登錄驗證
/// <summary> ///ResourceOwnerPassword模式下用於自定義登錄驗證 /// </summary> public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator { private readonly IConfiguration config; public ResourceOwnerPasswordValidator(IConfiguration config) { this.config = config; } public Task ValidateAsync(ResourceOwnerPasswordValidationContext context) { //根據context.UserName和context.Password與數據庫的數據做校驗,判斷是否合法 if (context.UserName == "test" && context.Password == "test") { context.Result = new GrantValidationResult( subject: context.UserName, authenticationMethod: OidcConstants.AuthenticationMethods.Password); } else { //驗證失敗 context.Result = new GrantValidationResult( TokenRequestErrors.InvalidGrant, "invalid custom credential" ); } return Task.FromResult(0); } }
6、在 Startup 配置IdentityServer
public class Startup { // This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { services.AddIdentityServer() //配置證書 .AddDeveloperSigningCredential() //配置API資源 .AddInMemoryApiResources(Config.GetApis()) //配置身份資源 .AddInMemoryIdentityResources(Config.GetIdentityResources()) //預置Client .AddInMemoryClients(Config.GetClients()) .AddProfileService<ProfileService>() .AddResourceOwnerValidator<ResourceOwnerPasswordValidator>(); services.AddAuthentication() .AddCookie(options => { options.ExpireTimeSpan = System.TimeSpan.FromMinutes(30); options.SlidingExpiration = 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(); } app.UseIdentityServer();//IdentityServer4中間件 app.Run(async (context) => { await context.Response.WriteAsync("IdentityServer4"); }); } }
到這里我們IdentityServer4服務端已經搭建好了,我們用postman測試下,這里調用的是ResourceOwnerPassword模式
二、.net framework webapi 配置
1、新建一個 .net framework webapi 程序
\
2、由於webapi是.net Framework版本的,所以我們需要引用 IdentityServer3.AccessTokenValidation 作為api端token的驗證組件。
Nuget添加:
IdentityServer3.AccessTokenValidation
IdentityModel
Microsoft.Owin.Host.SystemWeb
3、添加一個 Owin Startup.cs ,最好是用現有的startup類,而不要自己去新建一個類,然后修改名稱。
4、在Startup中配置 IdentityServer AccessToken 驗證參數
public class Startup { public void Configuration(IAppBuilder app) { app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions { Authority = "http://localhost:62527/", RequiredScopes = new[] { "FrameworkAPI" },//對應Client中配置的AllowedScopes和ApiResource DelayLoadMetadata = true }); } }
5、在 WebAPIConfig 中加入 config.Filters.Add(new AuthorizeAttribute()) 來啟用授權驗證
config.Filters.Add(new AuthorizeAttribute());
6、添加TestController
public class TestController : ApiController { public IHttpActionResult Get() { var user = User as ClaimsPrincipal; var claims = from c in user.Claims select new { type = c.Type, value = c.Value }; return Json(claims); } }
最后項目結構如下:
三、測試
我們的服務端和webapi都已經配置好了,我們用postman測試下
1、直接訪問api地址 http://localhost:44387/test ,不加入token ,得到如下結果,返回401
2、加入token ,驗證通過,返回200