1.新建项目并添加引用
新建一个asp .net core 2.0的项目
引用IdentityServer4.AspNetIdentity
2.定义资源
新建Config.cs文件,定义Api资源与Identity资源
资源分为身份资源(Identity resources)和API资源(API resources)
(1)身份资源(Identity resources)
身份资源是用户的用户名,姓名或电子邮件地址等数据。身份资源具有唯一的名称,可以为其分配任意声明类型。然后,这些声明将被包含在用户的身份令牌中。客户端将使用scope参数来请求访问身份资源。
身份资源可以是IdentityServer自带的资源,也可以是自定义的资源。
public static IEnumerable GetIdentityResources()
{
//自定义身份资源
var customProfile = new IdentityResource(
name: "custom.profile",
displayName: "Custom profile",
claimTypes: new[] { "name", "email", "status" });
return new List
{
//IdentityServer自带的资源
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
customProfile
};
}
(2)API资源(API resources)
API资源是客户端访问API获得的资源
public static IEnumerable GetApiResources()
{
return new List
{
//具有单一范围的简单API(在这种情况下,范围名称与api名称相同)
new ApiResource("api1", "My API"),
// 扩展版本,更多的设置选项
new ApiResource
{
Name = "api2",
// 用于内部校验的密码
// ApiSecrets是用于内部校验的,API的名称(Name)和密码(ApiSecrets)可以用于认证
ApiSecrets =
{
new Secret("secret".Sha256())
},
// 在访问令牌中包含以下内容(除了subject ID)
// UserClaims表示用户声明
UserClaims = { JwtClaimTypes.Name, JwtClaimTypes.Email },
// // 该API定义了两个范围
Scopes =
{
new Scope()
{
Name = "api2.full_access",
DisplayName = "Full access to API 2",
},
new Scope
{
Name = "api2.read_only",
DisplayName = "Read only access to API 2"
}
}
}
};
}
3.定义客户端Client
客户端指想要访问资源的Client
public static IEnumerable GetClients()
{
return new List
{
//不一定要配置得这么复杂,根据需求来
new Client
{
ClientId = "mvc",
ClientName = "MVC Client",
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
RequireConsent = true,
ClientSecrets =
{
new Secret("secret".Sha256())
},
//这里配置客户端的网址,多个客户端则是多个网址
RedirectUris = { "http://localhost:5002/signin-oidc" },
PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },
//允许的范围
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api1"
},
AllowOfflineAccess = true
}
};
}
其他配置请参阅:
https://identityserver4.readthedocs.io/en/release/topics/clients.html
4.配置
把资源信息和客户端信息交给IdentityServer
public void ConfigureServices(IServiceCollection services)
{
//配置服务
services.AddIdentityServer()
//读取客户端列表
.AddInMemoryClients(Clients.Get())
//读取身份资源列表
.AddInMemoryIdentityResources(Resources.GetIdentityResources())
//读取API资源列表
.AddInMemoryApiResources(Resources.GetApiResources())
//设置临时签名凭据
.AddDeveloperSigningCredential()
//添加测试用户
.AddTestUsers(TestUsers.Users);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//配置管道:注意配置管道要写在路由的前面...
app.UseIdentityServer();
}
这里需要注意的是,以上的资源信息和客户端信息是存在内存中的,可以设置为读取数据库
参阅:https://identityserver4.readthedocs.io/en/release/quickstarts/8_entity_framework.html
5.多客户端的统一登录
(1)用户表
//ApplicationUser继承于IdentityUser,可以在此为用户表添加属性,字段
public class ApplicationUser : IdentityUser
{
}
(2)页面
(3)登录方法
这里是AspNet Identity的内容
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task Login(LoginViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
// 尝试登录
// 需要注意的是,这里没有对登录失败进行计数
// 为了在登录失败多次之后触发锁定用户,把lockoutOnFailure设置为true
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
_logger.LogInformation("User logged in.");
return RedirectToLocal(returnUrl);
}
if (result.RequiresTwoFactor)
{
return RedirectToAction(nameof(LoginWith2fa), new { returnUrl, model.RememberMe });
}
if (result.IsLockedOut)
{
_logger.LogWarning("User account locked out.");
return RedirectToAction(nameof(Lockout));
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(model);
}
}
return View(model);
}
6.设置IdentityServer项目的端口号为5000
7.其他
整个流程还需要包括注册,注销,忘记密码,第三方登录,修改用户信息等,这些不属于IdentityServer的讨论范畴,在此不做讨论