前言
OAuth 2.0默認四種授權模式(GrantType)
- 授權碼模式(authorization_code)
- 簡化模式(implicit)
- 密碼模式(resource owner password credentials)
- 客戶端模式(client_credentials)
本章主要介紹密碼模式(resource owner password credentials),OAuth2.0資源所有者密碼授權功能允許客戶端將用戶名和密碼發送到令牌服務,並獲得該用戶的訪問令牌.
認證步驟:
- 用戶將用戶名密碼提供給客戶端
- 客戶端再將用戶名密碼發送給授權服務器,請求令牌
- 授權服務器確定判斷信息是否有誤,返回給客戶端令牌
創建授權服務器
創建一個API項目工程,我這邊以端口5000的形式進行后面的講解.
Package
PM> Install-package IdentityServer4 -version 2.5.3
創建一個類Config(配置要保護的資源,和可以訪問的API的客戶端服務器)
public class Config
{
/// <summary>
/// 定義要保護的資源
/// </summary>
/// <returns></returns>
public static IEnumerable<ApiResource> GetApiResources() {
return new List<ApiResource>
{
new ApiResource("api1","MyApi")
};
}
/// <summary>
/// 定義授權客戶端
/// </summary>
/// <returns></returns>
public static IEnumerable<Client> GetClients() {
return new List<Client>
{
new Client(){
ClientId="client",
AllowedGrantTypes=GrantTypes.ResourceOwnerPassword,
ClientSecrets=
{
new Secret("secret".Sha256())
},
AllowedScopes={ "api1",IdentityServerConstants.StandardScopes.OfflineAccess //如果要獲取refresh_tokens ,必須在scopes中加上OfflineAccess
},
AllowOfflineAccess=true// 主要刷新refresh_token,
}
};
}
}
此處AllowedGrantTypes需要設置為ResourceOwnerPassword(密碼憑證).
配置Startup
再走到ConfigureServices方法注入IdentityServer4服務
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddResourceOwnerValidator<ResourceOwnerPasswordValidator>();//注入自定義登錄驗證
}
IdentityServer4默認提供了兩種證書加密配置
AddDeveloperSigningCredential AddTemporarySigningCredential
添加內存ApiResourceAddInMemoryApiResources
添加內存Client AddInMemoryClients
添加自定義登錄驗證AddResourceOwnerValidator
自定義用戶驗證
public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
{
public Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
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);
}
}
在Configure方法中添加IdentityServer4服務中間件
app.UseIdentityServer();
創建ApiResource
創建一個客戶端項目,這邊我將端口設置為5001
Package
PM> Install-package IdentityServer4 -version 2.5.3
配置Startup
在ConfigureServices添加認證服務器地址
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = "http://localhost:5000";//授權服務器地址
options.RequireHttpsMetadata = false;//不需要https
options.ApiName = "api1";
});
}
在Configure方法中添加認證服務中間件
app.UseAuthentication();
Run
在客戶端程序values控制器上面增加[Authorize]
直接訪問資源服務器http://localhost:5001/api/values
code 401
啟動授權服務器
http://localhost:5000/.well-known/openid-configuration
發現端點可通過/.well-known/openid-configuration
獲取token
這邊我用postman進行測試
code 200
access_token我們獲取到了,再拿着token通過postman請求資源程序,
code 200
成功了
refresh_token
獲取請求授權接口后會返回access_token expires
_in 等內容,expires_in是有效期(s),當然我們可以自定義有效期,access_token失效后用戶需要重新授權,client才能拿到新的access_token.但是有了refresh_token后,client檢測到token失效后可以直接通過refresh_token向授權服務器申請新的token,當然refresh_token也是有有效期的。
AbsoluteRefreshTokenLifetime的默認有效期為2592000秒/30天。SlidingRefreshTokenLifetime的默認有效期為1296000秒/15天。
在認證服務器中我再scopes加上了OfflineAccess
IdentityServerConstants.StandardScopes.OfflineAccess //如果要獲取refresh_tokens ,必須在scopes中加上OfflineAccess
獲取refresh_token
通過refresh_token再去獲取access_token
通過postman請求獲取資源
概要