IdentityServer4 实现单点登录
服务端
public class Config
{
/// <summary>
/// IDS资源
/// </summary>
/// <returns></returns>
public static IEnumerable<IdentityResource> GetIds()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
};
}
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("UserCenter", "UserCenter API")
};
}
public static IEnumerable<ApiScope> GetApiScopes()
{
return new List<ApiScope>
{
new ApiScope("UserCenter", "UserCenter API")
};
}
/// <summary>
/// 可以使用ID4 Server 客户端资源
/// </summary>
/// <returns></returns>
public static IEnumerable<Client> GetClients()
{
List<Client> clients = new List<Client>() {
////授权码模式
//new Client
//{
// ClientId = "client1",
// ClientSecrets = { new Secret("123456".Sha256()) },
// //授权码模式
// AllowedGrantTypes = GrantTypes.Code,
// //需要确认授权
// RequireConsent = true,
// RequirePkce = true,
// //允许token通过浏览器
// AllowAccessTokensViaBrowser=true,
// // where to redirect to after login(登录)
// RedirectUris = { "https://localhost:7072/signin-oidc" },
// // where to redirect to after logout(退出)
// PostLogoutRedirectUris = { "https://localhost:7072/signout-callback-oidc" },
// //允许的范围
// AllowedScopes = new List<string>
// {
// IdentityServerConstants.StandardScopes.OpenId,
// IdentityServerConstants.StandardScopes.Profile,
// "UserCenter"
// },
// AlwaysIncludeUserClaimsInIdToken=true
//},
new Client
{
ClientId = "client2",
ClientSecrets = { new Secret("123456".Sha256()) },
//混合与客户端模式
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
//需要确认授权
RequireConsent = true,
RequirePkce = false,
//允许token通过浏览器
AllowAccessTokensViaBrowser=true,
// where to redirect to after login(登录)
RedirectUris = { "https://localhost:7072/signin-oidc" },
// where to redirect to after logout(退出)
PostLogoutRedirectUris = { "https://localhost:7072/signout-callback-oidc" },
AccessTokenLifetime = 3600,//Token 过期时间
//AccessTokenType= AccessTokenType.Jwt,
AlwaysIncludeUserClaimsInIdToken = true,//将用户所有的claims包含在IdToken内
//AbsoluteRefreshTokenLifetime = 2592000,//RefreshToken的最长生命周期,默认30天
//RefreshTokenExpiration = TokenExpiration.Sliding,//刷新令牌时,将刷新RefreshToken的生命周期。RefreshToken的总生命周期不会超过AbsoluteRefreshTokenLifetime。
//SlidingRefreshTokenLifetime = 3600,//以秒为单位滑动刷新令牌的生命周期。
AllowOfflineAccess = true,//如果要获取refresh_tokens ,必须把AllowOfflineAccess设置为true
//允许的范围
AllowedScopes = new List<string>
{
//"UserCenter",
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
},
}
};
return clients;
}
/// <summary>
/// 定义可以使用ID4的用户资源
/// </summary>
/// <returns></returns>
public static List<TestUser> GetUsers()
{
return new List<TestUser>()
{
new TestUser
{
SubjectId = "001",
Username = "ypf1", //账号
Password = "1", //密码
Claims =
{
new Claim(JwtClaimTypes.Name, "Alice Smith"),
new Claim(JwtClaimTypes.Email, "AliceSmith@email.com"),
}
},
new TestUser
{
SubjectId = "002",
Username = "ypf2",
Password = "1",
Claims =
{
new Claim(JwtClaimTypes.Name, "Bob Smith"),
new Claim(JwtClaimTypes.Email, "BobSmith@email.com"),
}
}
};
}
}
Startup 代码
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
//注册IDS4信息(授权码模式)
services.AddIdentityServer(options=> {
options.Authentication.CookieAuthenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddDeveloperSigningCredential()
.AddInMemoryIdentityResources(Config.GetIds())
.AddInMemoryClients(Config.GetClients())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryApiScopes(Config.GetApiScopes())
.AddTestUsers(Config.GetUsers());
services
.AddAuthentication(options=> {
//默认为Cookie 同时支持Jwt
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
// IdentityServer4 地址
options.Authority = "http://localhost:7071";
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = false,//是否验证Issuer
ValidateAudience = false,//是否验证Audience
ValidateLifetime = true,//是否验证失效时间
ValidateIssuerSigningKey = false,//是否验证SecurityKey
//ValidAudience = "UserCenter",//Audience
//ValidIssuer = "yourdomain.com",//Issuer,这两项和前面签发jwt的设置一致
//ValidAudiences = new List<string>() { "client2" }//, "api1"
};
});
}
// 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();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
//启用IDS4
app.UseIdentityServer();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
api 使用jwt验证
[Route("api/[controller]/[action]")]
[ApiController]
[Authorize(AuthenticationSchemes=JwtBearerDefaults.AuthenticationScheme)]//(JwtBearerDefaults.AuthenticationScheme)
public class DemoController : ControllerBase
{
[Authorize]
public JsonResult Index()
{
//string str = OpenIdConnectParameterNames.RefreshToken;
string accessToken = HttpContext.GetTokenAsync("access_token").Result;
string idToken = HttpContext.GetTokenAsync("id_token").Result;
var refreshToken = HttpContext.GetTokenAsync("refresh_token").Result;
var claimsList = from c in User.Claims select new { c.Type, c.Value };
return new JsonResult(new
{
data = new
{
accessToken,
idToken,
refreshToken,
claimsList
}
});
}
}
同时服务端需要下载IdentityServer4.Quickstart.UI 代码 (github上有)
以下3个文件复制到你的服务端项目中

客户端
Startup代码
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
//添加Cookie认证
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
//通过OIDC协议远程请求认证
.AddOpenIdConnect("oidc", options =>
{
options.Authority = "http://localhost:7071"; //认证授权服务器地址
#region 授权码模式
//options.RequireHttpsMetadata = false;
//options.ClientId = "client1"; //客户端ID
//options.ClientSecret = "123456"; //客户端秘钥
////授权码模式
//options.ResponseType = OpenIdConnectResponseType.Code;
//options.ResponseMode = OpenIdConnectResponseMode.Query;
//options.SaveTokens = true;
#endregion
#region 混合客户端模式
options.RequireHttpsMetadata = false;
options.ClientId = "client2"; //客户端ID
options.ClientSecret = "123456"; //客户端秘钥
//混合客户端模式
options.ResponseType = OpenIdConnectResponseType.CodeIdTokenToken;
//options.ResponseMode = OpenIdConnectResponseMode.Query;
options.SaveTokens = true;
#endregion
});
}
// 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();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
//开启认证
app.UseAuthentication();
//开启授权
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
客户端api增加授权控制,在没有授权的情况下访问,客户端会跳转到服务端登录进行认证,认证通过会转回到客户端
这里服务端认证中心可以提供获取用户信息接口,客户端可以使用拿到的token请求认证中心的用户信息接口

浙公网安备 33010602011771号