radmin提示授权码过期_IdentityServer4 客户端授权模式(Client Credentials)
(給DotNet加星標,提升.Net技能)
轉(zhuǎn)自:朝閑cnblogs.com/Zing/p/13361386.html前言
1、源碼(.NET Core 2.2)
git地址:https://github.com/yizhaoxian/CoreIdentityServer4Demo.git
2、相關章節(jié)
2.1、《IdentityServer4 (1) 客戶端授權模式(Client Credentials)》
2.2、《IdentityServer4 (2) 密碼授權(Resource Owner Password)》
2.3、《IdentityServer4 (3) 授權碼模式(Authorization Code)》
2.4、《IdentityServer4 (4) 靜默刷新(Implicit)》
2.5、《IdentityServer4 (5) 混合模式(Hybrid)》
3、參考資料
IdentityServer4 中文文檔 http://www.identityserver.com.cn/
IdentityServer4 英文文檔 https://identityserver4.readthedocs.io/en/latest/
4、流程圖
客戶端授權模式是最基本的使用場景,我們需要做一個API(受保護的資源),一個客戶端(訪問的應用),一個IdentityServer(用來授權)
一、創(chuàng)建IdentityServer
1、用VS創(chuàng)建一個Web 項目
2、添加引用 IdentityServer4 包,下圖是我已經(jīng)安裝好了的截圖
3、添加一個配置文件(這里也可以使用json文件)
public class IdpConfig{
///
/// 用戶認證信息
///
///
public static IEnumerableGetApiResources(){
return new List
{new IdentityResources.OpenId(),new IdentityResources.Profile(),new IdentityResources.Address(),new IdentityResources.Email(),new IdentityResources.Phone()
};
}/// /// API 資源/// /// public static IEnumerableGetApis(){return new List
{new ApiResource("api1", "My API")
};
}/// /// 客戶端應用/// /// public static IEnumerableGetClients(){return new List
{new Client
{// 客戶端ID 這個很重要
ClientId = "client",//AccessToken 過期時間,默認3600秒,注意這里直接設置5秒過期是不管用的,解決方案繼續(xù)看下面 API資源添加JWT//AccessTokenLifetime=5,// 沒有交互性用戶,使用 clientid/secret 實現(xiàn)認證。
AllowedGrantTypes = GrantTypes.ClientCredentials,// 用于認證的密碼
ClientSecrets =
{new Secret("secret".Sha256())
},// 客戶端有權訪問的范圍(Scopes)
AllowedScopes = { "api1" }
}
};
}
}
4、在StartUp.cs 里注冊 IdentityServer4?
ConfigureServices()
services.AddIdentityServer(options =>{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
})
.AddDeveloperSigningCredential()//解決Keyset is missing 錯誤
//.AddTestUsers(TestUsers.Users)
//.AddInMemoryIdentityResources(IdpConfig.GetApiResources())
.AddInMemoryApiResources(IdpConfig.GetApis())
.AddInMemoryClients(IdpConfig.GetClients());
Configure()方法添加使用 IdentityServer4 中間件
app.UseIdentityServer();5、配置完成
啟動項目,訪問 http://localhost:5002/.well-known/openid-configuration (我的端口號是5002) ,可以瀏覽 發(fā)現(xiàn)文檔,參考下圖,說明已經(jīng)配置成功。
后面客戶端會使用里面的數(shù)據(jù)進行請求toke
項目第一次啟動根目錄也會生成一個文件 tempkey.rsa
二、客戶端
1、新建一個.Net Core Web 項目
這里可以使用其他建立客戶端 。例如:控制臺程序、wpf 等等。需要添加 NuGet 包 IdentityModel
2、新建一個 Controller 用來測試訪問上面的IdentityServer
獲取token,訪問 http://localhost:5003/Idp/token ,提示訪問成功
public class IdpController : Controller{
private static readonly string _idpBaseUrl = "http://localhost:5002";
public async TaskToken(){
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync(_idpBaseUrl);
if (disco.IsError)
{
return Content("獲取發(fā)現(xiàn)文檔失敗。error:" + disco.Error);
}
var token = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest()
{
Address = disco.TokenEndpoint,
//ClientId、ClientSecret、Scope 這里要和 API 里定義的Client一模一樣
ClientId = "client",
ClientSecret = "secret",
Scope = "api1"
});
if (token.IsError)
{
return Content("獲取 AccessToken 失敗。error:" + disco.Error);
}
return Content("獲取 AccessToken 成功。Token:" + token.AccessToken);
}
}
三、添加API資源
1、新建一個API項目
我把API項目和IdentityServer 放到同一個解決方案,這個自己定,無所謂的
API資源指的是IdentityServer IdpConfig.GetApis() 里面添加的 api1(這個api1名稱隨便起,但是要注意一定要保持一致)
添加認證之后就可以測試用 AccessToken 請求資源了
2、添加JWT 認證
StartUp.ConfigureServices()
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
// IdentityServer 地址
options.Authority = "http://localhost:5002";
//不需要https
options.RequireHttpsMetadata = false;
//這里要和 IdentityServer 定義的 api1 保持一致
options.Audience = "api1";
//token 默認容忍5分鐘過期時間偏移,這里設置為0,
//這里就是為什么定義客戶端設置了過期時間為5秒,過期后仍可以訪問數(shù)據(jù)
options.TokenValidationParameters.ClockSkew = TimeSpan.Zero;
options.Events = new JwtBearerEvents
{
//AccessToken 驗證失敗
OnChallenge = op =>
{
//跳過所有默認操作
op.HandleResponse();
//下面是自定義返回消息
//op.Response.Headers.Add("token", "401");
op.Response.ContentType = "application/json";
op.Response.StatusCode = StatusCodes.Status401Unauthorized;
op.Response.WriteAsync(JsonConvert.SerializeObject(new
{
status = StatusCodes.Status401Unauthorized,
msg = "token無效"
}));
return Task.CompletedTask;
}
};
});
3、添加認證中間件
//這里注意 一定要在 UseMvc前面,順序不可改變app.UseAuthentication();
4、Controller 添加特性認證 [Authorize]
[Route("api/[controller]")][Authorize]
public class SuiBianController : Controller
{
[HttpGet]
public string Get(){
var roles = User.Claims.Where(l => l.Type == ClaimTypes.Role);
return "訪問成功,當前用戶角色 " + string.Join(',', roles.Select(l => l.Value));
}
}
5、測試
訪問 http://localhost:5001/api/suibian ,提示 token 無效,證明我們增加認證成功
四、客戶端測試
1、修改 IdpController, 添加一個action 訪問 API資源 /api/suibian
public class IdpController : Controller{//內(nèi)存緩存 需要提前注冊 services.AddMemoryCache();private IMemoryCache _memoryCache; private static readonly string _idpBaseUrl = "http://localhost:5002";private static readonly string _apiBaseUrl = "http://localhost:5001";public IdpController(IMemoryCache memoryCache){
_memoryCache = memoryCache;
}public async TaskToken(){var client = new HttpClient();var disco = await client.GetDiscoveryDocumentAsync(_idpBaseUrl);if (disco.IsError)
{return Content("獲取發(fā)現(xiàn)文檔失敗。error:" + disco.Error);
}var token = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest()
{
Address = disco.TokenEndpoint,
ClientId = "client",
ClientSecret = "secret",
Scope = "api1"
});if (token.IsError)
{return Content("獲取 AccessToken 失敗。error:" + disco.Error);
}//將token 臨時存儲到 緩存中
_memoryCache.Set("AccessToken", token.AccessToken);return Content("獲取 AccessToken 成功。Token:" + token.AccessToken);
}public async TaskSuiBian(){string token, apiurl = GetApiUrl("suibian");
_memoryCache.TryGetValue("AccessToken", out token);if (string.IsNullOrEmpty(token))
{return Content("token is null");
}var client = new HttpClient();
client.SetBearerToken(token);var response = await client.GetAsync(apiurl);var result = await response.Content.ReadAsStringAsync();if (!response.IsSuccessStatusCode)
{
_memoryCache.Remove("AccessToken");return Content($"獲取 {apiurl} 失敗。StatusCode:{response.StatusCode} \r\n Token:{token} \r\n result:{result}");
}return Json(new
{
code = response.StatusCode,
data = result
});
}private string GetApiUrl(string address){return _apiBaseUrl + "/api/" + address;
}
}
2、請求 AccessToken
http://localhost:5003/Idp/token ,請求成功后會將 token 存儲到 cache 中
3、請求 API 資源
http://localhost:5003/Idp/suibian ,token是直接在緩存里面取出來的
五、項目目錄
- EOF -
推薦閱讀??點擊標題可跳轉(zhuǎn).NET hbase client--終于浮出水面的輪子
WinUI 3 試玩報告:10 篇熱文匯總
ASP.NET Core監(jiān)聽SQL Server數(shù)據(jù)庫的實時信息
看完本文有收獲?請轉(zhuǎn)發(fā)分享給更多人
關注「DotNet」加星標,提升.Net技能?
好文章,我在看??
總結
以上是生活随笔為你收集整理的radmin提示授权码过期_IdentityServer4 客户端授权模式(Client Credentials)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 宝塔定时任务执行php源码任务_Linu
- 下一篇: 时隙aloha协议仿真程序_工控Modb