首页 >> 大全

二.客户端凭据的认证方式

2023-08-27 大全 27 作者:考证青年

 public static class Config{//定义APIpublic static IEnumerable<ApiScope> ApiScopes =>new List<ApiScope>{new ApiScope("api1", "My API")};//定义客户端// 定义访问 API 的客户端应用// 这种情况下,客户端没有交互式的用户,只能通过客户端密钥进行身份验证。// ClientId 和 Client Secret 可以视为登录名和密码。让身份认证服务器知道是哪个用户。public static IEnumerable<Client> Clients => new List<Client>{new Client{// 定义一个客户端ClientId = "client",// 认证类型。//使用客户端密钥的方式进行验证。AllowedGrantTypes = GrantTypes.ClientCredentials,// 认证的密码ClientSecrets ={new Secret("secret".Sha256())},// 这个客户端端可以访问的 APIAllowedScopes = { "api1" }}};

2.在 里面做调用设置

  public Startup(IConfiguration configuration){Configuration = configuration;}public IConfiguration Configuration { get; }public void ConfigureServices(IServiceCollection services){services.AddControllers();var builder = services.AddIdentityServer().AddInMemoryApiScopes(Config.ApiScopes) // 那个api可以使用.AddInMemoryClients(Config.Clients)// 哪个client可以使用.AddDeveloperSigningCredential() ;//解决连接不上的问题,实际中,签名需要一对公钥和私钥,他会帮我们将公钥和私钥存储到硬盘上}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseRouting();app.UseIdentityServer();//使用 Identity 4app.UseEndpoints(endpoints =>{endpoints.MapControllers();});}

重生成,而使用命令行运行一下

… --urls *:5001

2.建立受保护的API

1.建立要访问受保护的

[ApiController]public class IdentityController : ControllerBase{[HttpGet("identity")][Authorize]public IActionResult Get(){return new JsonResult(from c in User.Claims select new { c.Type, c.Value });}[Authorize][HttpGet("test")]public string Getst(){return "受保护的 API 访问成功";}}

2.在 里面进行配置

  public void ConfigureServices(IServiceCollection services){services.AddControllers();//接受授服务器发送的任何访问令牌。services.AddAuthentication("Bearer").AddJwtBearer("Bearer", options =>{options.Authority = "https://localhost:5001";options.TokenValidationParameters = new TokenValidationParameters{ValidateAudience = false};});// 允许检测客户端请求的令牌中是否存在作用域services.AddAuthorization(options =>{options.AddPolicy("ApiScope", policy =>{policy.RequireAuthenticatedUser();policy.RequireClaim("scope", "api1");});});}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseRouting();app.UseAuthentication();//每次都要执行身份验证.app.UseAuthorization(); //授权,确保匿名客户端无法访问我们的 api 端点app.UseEndpoints(endpoints =>{endpoints.MapControllers();});}

3.建立用来访问的客户端

  public class Program{// IdentityModel包括一个与发现端点一起使用的客户端库。这样,您只需要知道IdentityServer的基地址-可以从元数据中读取实际的端点地址://找到授权的服务器public static async System.Threading.Tasks.Task Main(string[] args){//找到授权服务器var client = new HttpClient();var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5001");  //异步的方法名前边必须声明 asyncif (disco.IsError){Console.WriteLine($"连接失败****{disco.Error}");return;}//向授权服务器请求 tokenvar tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest{Address = disco.TokenEndpoint,ClientId = "client",ClientSecret = "secret",Scope = "api1"});if (tokenResponse.IsError){Console.WriteLine("token返回错误", tokenResponse.Error);return;}Console.WriteLine(tokenResponse.Json);//将访问令牌发送给 APIvar apiClient = new HttpClient();apiClient.SetBearerToken(tokenResponse.AccessToken);var response = await apiClient.GetAsync("http://localhost:6001/test");if (!response.IsSuccessStatusCode){Console.WriteLine(response.StatusCode);Console.WriteLine("访问失败");}else{var content = await response.Content.ReadAsStringAsync();Console.WriteLine("访问成功");// Console.WriteLine(JArray.Parse(content));Console.WriteLine(content);}Console.ReadLine();}

具体查看gitee代码:

4.保护WPF客户端

这种是有用户参与的,使用的是 Grant (用名名密码)这种授权方式。

1.流程

运行的顺序和字母的顺序是一致的:

所以在这个过程之中,即对用户进行身份认证,也对浏览器进行身份认证。

具体操作看代码吧。我也没用过MVC

2.为MVC刷新 token

使用 Token 刷新 Token。

1.在MVC 客户端进行设置

 new Client{ClientId = "mvc client",ClientName = "ASP.NET Core MVC Client", // 随便写AllowedGrantTypes = GrantTypes.CodeAndClientCredentials,//允许两种授权方式.ClientSecrets = { new Secret("mvc secret".Sha256()) },//密码.//下边都是固定的地址。RedirectUris = { "http://localhost:5002/signin-oidc" },FrontChannelLogoutUri = "http://localhost:5002/signout-oidc",PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },AlwaysIncludeUserClaimsInIdToken = true,AllowOfflineAccess = true, // offline_access//默认是一个小时。现在改成 60s 。AccessTokenLifetime = 60, // 60 secondsAllowedScopes ={"api1",IdentityServerConstants.StandardScopes.OpenId,IdentityServerConstants.StandardScopes.Email,IdentityServerConstants.StandardScopes.Address,IdentityServerConstants.StandardScopes.Phone,IdentityServerConstants.StandardScopes.Profile}},

但是仅仅这样设置,过了一分钟以后,进入 MVC ,依然还能得到 API 的相关信息 。这是因为我们的 API 没有设置对于 对于token检验。

2.对受保护的 API进行设置

        services.AddAuthentication("Bearer")//bearer 的授权方式。.AddJwtBearer("Bearer", options =>{options.Authority = "https://localhost:5000";options.RequireHttpsMetadata = false;//不需要httpsoptions.TokenValidationParameters = new         TokenValidationParameters{ValidateAudience = false};//每隔一分钟,验证一次这个tokenoptions.TokenValidationParameters.RequireExpirationTime = true;//必须要有超时时间这个参数。options.TokenValidationParameters.ClockSkew = TimeSpan.FromMinutes(1);});

3.刷新 Token

在 MVC 的控制器里面,再添加一个 ,用来刷新 Token。

   //刷新 tokenprivate async Task<string> RenewTokensAsync(){//发现文档var client = new HttpClient();var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5000");if (disco.IsError){throw new Exception(disco.Error);}//获取 refreshTokenvar refreshToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.RefreshToken);//请求tokenvar tokenResponse = await client.RequestRefreshTokenAsync(new RefreshTokenRequest{Address = disco.TokenEndpoint,ClientId = "mvc client",ClientSecret = "mvc secret",Scope = "api1 openid profile email phone address",GrantType = OpenIdConnectGrantTypes.RefreshToken,RefreshToken = refreshToken});if (tokenResponse.IsError){throw new Exception(tokenResponse.Error);}//超时时间,使用的是 UTC 时间。var expiresAt = DateTime.UtcNow + TimeSpan.FromSeconds(tokenResponse.ExpiresIn);// 把 token 数组全部集中起来,做成一个数组。var tokens = new[]{new AuthenticationToken{Name = OpenIdConnectParameterNames.IdToken,Value = tokenResponse.IdentityToken},new AuthenticationToken{Name = OpenIdConnectParameterNames.AccessToken,Value = tokenResponse.AccessToken},new AuthenticationToken{Name = OpenIdConnectParameterNames.RefreshToken,Value = tokenResponse.RefreshToken},new AuthenticationToken{Name = "expires_at",Value = expiresAt.ToString("o", CultureInfo.InvariantCulture)}};// 获取身份认证的结果,包含当前的pricipal和propertiesvar currentAuthenticateResult =await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);// 把获得的token再更新一遍。currentAuthenticateResult.Properties.StoreTokens(tokens);// 再进行以下登录动作.await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,currentAuthenticateResult.Principal, currentAuthenticateResult.Properties);// 再把 access token 返回过去.return tokenResponse.AccessToken;}

在前边用到token的地方,再更新一下这个方法:

 var response = await client.GetAsync("http://localhost:5001/identity");if (!response.IsSuccessStatusCode){if (response.StatusCode == HttpStatusCode.Unauthorized){await RenewTokensAsync();return RedirectToAction();}throw new Exception(response.ReasonPhrase);}

5. Flow 6. Flow

使用 保护 api 资源。

之前使用的 隐式流,所有的令牌都是通过浏览器来传输,这对于 ID token 来说当然没有问题,但是我们还想请求一个 token, 更加敏感,所以在没有必要的时候,我们不会想把他暴露给外部世界, 包含了一个叫做 “混合流( flowe)”,它为我们提供了两方面的优点,身份令牌通过浏览器频道来传输,这样客户端就能能够在做任何工作前验证他,如果验证成功,客户端就会打开一个后端通道,来链接令牌,以检索访问令牌。

1.客户端类型 机密客户端:这种客户端有能力维护其凭据的机密性。位于服务端,例如服务器端的 Web 应用,例如 MVC。公开客户端:这种客户端无法维持其凭据的机密性,位于客户端设备,例如 JS 应用,移动应用,原生应用和软件等。

.和相比 就是相当于多出来一个 Flow

2.返回类型

根据 的不同,分为三种情况:

3.角色和策略 3.1基于角色

在注册的用户里面直接声明 管理员角色

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了