Asp.Net WebApi 接入 Identity Server4 全记录
Asp.Net WebApi 接入 Identity Server4 全记录
当前环境
Net Core 2.2+ // 建议使用 Net Core 3.0
Asp.Net Framework 4.6.2+
Visual Studio 2019// 如果使用 Net Core 3.0,你可能需要预览版
新增空的解决方案
- 打开命令行。执行
dotnet new sln -n SsoTest
建立空白解决方案。
新增 Identity Server4 服务端【本文不讨论服务端配置问题】
新增项目并添加到解决方案里
打开命令行或者 powershell
1
2
3
4
5
6
7
8
9
10# 新增IdentityServer4模板
dotnet new -i IdentityServer4.Templates
# 新建项目
dotnet new is4empty -n IdentityServer
# 添加到解决方案
dotnet sln add .\IdentityServer\IdentityServer.csproj
# 进入项目目录
cd IdentityServer
# 添加UI
dotnet new is4ui修改 Config.cs 文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116using IdentityServer4;
using IdentityServer4.Models;
using IdentityServer4.Test;
using System.Collections.Generic;
using System.Security.Claims;
namespace IdentityServer
{
public static class Config
{
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new IdentityResource[]
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResources.Email(),
new IdentityResources.Phone(),
};
}
public static List<TestUser> GetUsers()
{
return new List<TestUser> {
new TestUser {
SubjectId = "1",
Username = "alice",
Password = "password",
Claims = new []
{
new Claim("name", "Alice"),
new Claim("website", "https://alice.com")
}
},
new TestUser {
SubjectId = "2",
Username = "bob",
Password = "password",
Claims = new []
{
new Claim("name", "Bob"),
new Claim("website", "https://bob.com")
}
}
};
}
public static IEnumerable<ApiResource> GetApis()
{
return new ApiResource[] {
new ApiResource ("api1", "My API")
};
}
public static IEnumerable<Client> GetClients()
{
var secret = "49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".Sha256();
return new Client[] {
new Client {
ClientId = "mvc",
ClientName = "MVC Client",
ClientSecrets = {
new Secret (secret)
},
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
// where to redirect to after login
RedirectUris = { "http://localhost:5001/signin-oidc" },
// where to redirect to after logout
PostLogoutRedirectUris = { "http://localhost:5001/signout-callback-oidc" },
AllowedScopes = new List<string> {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Email,
IdentityServerConstants.StandardScopes.Phone,
IdentityServerConstants.StandardScopes.Profile,
"api1"
}
},,
new Client
{
ClientName = "vuejs",
ClientId = "vuejsclient",
AllowedGrantTypes=GrantTypes.Implicit,
AllowAccessTokensViaBrowser=true,
AccessTokenType = AccessTokenType.Reference,
UpdateAccessTokenClaimsOnRefresh = true,
AllowOfflineAccess = true,
RequireConsent = false,
//AccessTokenLifetime = 50,
RedirectUris = new List<string>()
{
"http://localhost:5002/static/callback.html",
"http://localhost:5002/static/silent-renew.html"
},
PostLogoutRedirectUris = {
"http://localhost:5002/index.html"
},
AllowedCorsOrigins = {
"http://localhost:5002"
},
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Address,
"roles",
"identityserver4api",
"country",
"subscriptionlevel"
},
ClientSecrets =
{
new Secret("secret".Sha256())
}
}
};
}
}
}修改 Startup.cs, 取消注释
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42public IHostingEnvironment Environment { get; }
public Startup(IHostingEnvironment environment)
{
Environment = environment;
}
public void ConfigureServices(IServiceCollection services)
{
// uncomment, if you want to add an MVC-based UI
services.AddMvc().SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_2_1);
var builder = services.AddIdentityServer()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApis())
.AddInMemoryClients(Config.GetClients())
.AddTestUsers(Config.GetUsers());
if (Environment.IsDevelopment())
{
builder.AddDeveloperSigningCredential();
}
else
{
throw new Exception("need to configure key material");
}
}
public void Configure(IApplicationBuilder app)
{
if (Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// uncomment if you want to support static files
app.UseStaticFiles();
app.UseIdentityServer();
// uncomment, if you want to add an MVC-based UI
app.UseMvcWithDefaultRoute();
}新开一个命令行或者 powershell 窗口,运行服务端
1
2
3
4
5
6
# 还原nuget,编译
dotnet restore
dotnet build
# 运行
dotnet run
新增一个空的 WebApi 项目
- 打开解决方案 SsoTest.sln
- 在解决方案上右键 -> 添加 -> 新建项目,创建 WebApi 项目,名为 SSOTest.WebApi
配置 WebApi 接入 Identity Server
修改项目属性,指定 web 端口为 5002
打开包控制台,安装 nuget 包
1
2
3Install-Package IdentityModel -Version 3.10.10
Install-Package IdentityServer3.Contrib.AccessTokenValidation
Install-Package Microsoft.Owin.Host.SystemWeb新增 OWIN 的 Startup.cs 文件
修改为 Startup.cs 文件.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39using System;
using System.Net.Http;
using System.Security.Claims;
using System.Web.Helpers;
using IdentityModel;
using IdentityModel.Client;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using Owin;
[assembly: OwinStartup(typeof(SSOTest.Client.Startup))]
namespace SSOTest.Client
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
// 有关如何配置应用程序的详细信息,请访问 https://go.microsoft.com/fwlink/?LinkID=316888
ConfigureAuth(app);
}
private void ConfigureAuth(IAppBuilder app)
{
var secret = "49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".ToSha256();
AntiForgeryConfig.UniqueClaimTypeIdentifier = "sub";
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = "http://localhost:5000",
RequiredScopes = new string[] { "webapi" },
ClientId = "Test",
ClientSecret = secret,
DelayLoadMetadata = true
});
}
}
}打开 Controllers/ValuesController.cs
在Get
这个 Action 上加特性[Authorize]
运行 Client 项目,访问 http://localhost:5002/Api/Values