好久没更新了,前几期使用了密码模式和客户端模式,本期将使用授权码模式实现单身登陆的操作,授权码模式是四个模式中的精髓,理论上的就不说了,大家自行百度,相信也不难,直接上代码。
1、新建服务端的项目具体流程和大部分文件与前几期密码模式相同,只是在Config.cs文件中,定义client时进行了改动。
return new List<Client> {
new Client {
ClientId="client1",
ClientSecrets={new Secret("api1".Sha256())},
AllowedGrantTypes=GrantTypes.Code,// 授权码模式
RequireConsent=false,
RequirePkce=true,
RedirectUris={ "http://localhost:4002/signin-oidc","http://localhost:4000/signin-oidc"}, // 各系统的客户端地址,其中signin-oidc是固定的
PostLogoutRedirectUris={ "http://localhost:4000/signout-callback-oidc","http://localhost:4002/signout-callback-oidc"},// 各系统的客户端地址,注销时使用
AllowedScopes=new List<string>{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api1", // 服务资源
},
// 增加离线授权访问
AllowOfflineAccess=true
}
};
2、引入模板,这块还需要再研究一下,界面是微软统一的,通用的,呵呵,还得花点时间变成自己想要的。
先安装模板
dotnet new -i identityserver4.templates
将模板安装到项目中
dotnet new is4ui
3、修改startup.cs文件
注意有一块是针对谷歌浏览器的代码,谷歌浏览器跳转问题的,之前貌似也不好用,后来我更新了谷歌浏览器后可以用了,也不知道是不是更新的问题。
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryApiScopes(Config.GetApiScopes())
.AddInMemoryClients(Config.GetClients())
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddTestUsers(Config.GetTestUsers().ToList());
services.AddCors(options => {
options.AddPolicy("any", builder =>
{
builder.WithOrigins("*");
});
});
services.AddControllersWithViews();
services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = Microsoft.AspNetCore.Http.SameSiteMode.Lax;
});//这块是用来针对谷歌浏览器跳转问题的
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCookiePolicy();
app.UseCors("any");
app.UseIdentityServer();
app.UseRouting();
app.UseStaticFiles();
app.UseEndpoints(endopint =>
{
endopint.MapDefaultControllerRoute();
});
}
好了,这里服务器端的就完成了,下面是客户端
5、新建客户端项目
用nuget引入一个包 Microsoft.AspNetCore.Authentication.OpenIdConnect,下这个的时候要注意跟.net core的版本对应,我用的是core 3.1,下的是3.16的版本,大家自行引入
startup.cs 文件内容
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddHttpClient();
//这块貌似也是对谷歌浏览器的或者HTTPS的,很奇怪,用IE没问题。用谷歌就有,更新后无此问题。
services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
options.OnAppendCookie = cookieContext =>
SetSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
SetSameSite(cookieContext.Context, cookieContext.CookieOptions);
});
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.Authority = "http://localhost:5000"; // 服务端地址
options.RequireHttpsMetadata = false;
options.ClientId = "client1";
options.ClientSecret = "api1";
options.ResponseType = "code";
options.SaveTokens = true;
options.Scope.Add("offline_access");
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("api1");
});
}
public void SetSameSite(HttpContext httpContext, CookieOptions options)
{
if (options.SameSite == SameSiteMode.None)
{
if (httpContext.Request.Scheme != "https")
{
options.SameSite = SameSiteMode.Unspecified;
}
}
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCookiePolicy();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthentication();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
6、新建一个控制器,加上鉴权属性,即可。
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IdentityClient.Controllers
{
[Authorize]
public class HomeController : Controller
{
[HttpGet]
public IActionResult Index()
{
return Content("bbb");
}
}
}
另外,多个客户端时就是startup.cs即可,然后在服务器端把地址加上,这块最好是用数据库模式。不然老改代码可不行,配置文件也可以,这期就到这里。