ASP.NET Web Forms and IdentityServer3
介紹:
我們有很多應用程式都使用出色的IdentityServer3作為我們的身份提供程式(或sso伺服器)。我們也有一些使用舊版ASP.NET Web窗體構建的應用程式。在我們的ASP.NET Web窗體中,我們進行了許多web.config授權檢查。我們的身份伺服器為經過身份驗證的使用者發行自包含的JWT令牌。我們的一些移動應用程式客戶端從身份伺服器獲取令牌,並將令牌傳送到我們的Web Forms應用程式。在我們的Web Forms應用程式中,我們只需要驗證JWT令牌。幸運的是,實現非常簡單。在本文中,我將向您展示如何驗證Web窗體中的自包含JWT令牌,以及如何在每個請求上設定經過身份驗證的使用者的執行緒/請求身份。
描述:
HttpApplication.AuthenticateRequest是IIS和ASP.NET都參與對請求進行身份驗證的地方。在這裡,我們將掛接我們的身份驗證邏輯並設定已身份驗證使用者的請求身份。我們可以在global.asax.cs檔案中新增此事件,也可以將其掛接到自定義HttpModule中。我將使用HttpModule。我們需要:1)新增對System.IdentityModel.dll程式集的引用。2)新增System.IdentityModel.Tokens.Jwt和Newtonsoft.Json nuget包。讓我們新增一個JsonWebTokenHttpModule類(請注意,我希望在Web Forms的請求中設定授權標頭,但同樣的技巧也適用於cookie
01 |
public class JsonWebTokenHttpModule : IHttpModule |
02 |
{ |
03 |
private static readonly Lazy< string > _securityKey = new Lazy< string >(() => GetSecurityKey()); |
04 |
05 |
private static string _authority = ConfigurationManager.AppSettings[ "Authority" ]; |
06 |
07 |
public void Init(HttpApplication context) |
08 |
{ |
09 |
context.AuthenticateRequest += new EventHandler(JsonWebTokenHandler); |
10 |
} |
11 |
12 |
private void JsonWebTokenHandler(Object source, EventArgs e) |
13 |
{ |
14 |
var context = HttpContext.Current; |
15 |
var request = context.Request; |
16 |
var authorizationHeader = request.Headers[ "Authorization" ]; |
17 |
if ( string .IsNullOrWhiteSpace(authorizationHeader) || !authorizationHeader.StartsWith( "Bearer " )) |
18 |
{ |
19 |
return ; |
20 |
} |
21 |
var token = authorizationHeader.Substring(7); |
22 |
try |
23 |
{ |
24 |
ValidateTokenAndSetIdentity(token); |
25 |
} |
26 |
catch (SecurityTokenValidationException ex) |
27 |
{ |
28 |
// log error here |
29 |
} |
30 |
catch |
31 |
{ |
32 |
// log error here |
33 |
} |
34 |
} |
35 |
36 |
private void ValidateTokenAndSetIdentity( string token) |
37 |
{ |
38 |
var tokenHandler = new JwtSecurityTokenHandler(); |
39 |
var validationParameters = GetValidationParameters(); |
40 |
SecurityToken validToken; |
41 |
var principal = tokenHandler.ValidateToken(token, validationParameters, out validToken); |
42 |
Thread.CurrentPrincipal = principal; |
43 |
HttpContext.Current.User = principal; |
44 |
} |
45 |
46 |
private static TokenValidationParameters GetValidationParameters() |
47 |
{ |
48 |
var bytes = Convert.FromBase64String(_securityKey.Value); |
49 |
var token = new X509SecurityToken( new X509Certificate2(bytes)); |
50 |
return new TokenValidationParameters |
51 |
{ |
52 |
ValidAudience = _authority + "/resources" , |
53 |
ValidIssuer = _authority, |
54 |
IssuerSigningKeyResolver = (arbitrarily, declaring, these, parameters) => { return token.SecurityKeys.First(); }, |
55 |
IssuerSigningToken = token |
56 |
}; |
57 |
} |
58 |
59 |
private static string GetSecurityKey() |
60 |
{ |
61 |
var webClient = new WebClient(); |
62 |
var endpoint = _authority + "/.well-known/openid-configuration" ; |
63 |
var json = webClient.DownloadString(endpoint); |
64 |
dynamic metadata = JsonConvert.DeserializeObject<dynamic>(json); |
65 |
var jwksUri = metadata.jwks_uri.Value; |
66 |
json = webClient.DownloadString(jwksUri); |
67 |
var key = JsonConvert.DeserializeObject<dynamic>(json).keys[0]; |
68 |
return ( string )key.x5c[0]; |
69 |
} |
70 |
71 |
public void Dispose() |
72 |
{ |
73 |
|
74 |
} |
75 |
} |
上面的HttpModule類將與任何可以釋出包含IdentityServer3的自包含JWT的開放ID連線提供程式一起使用。我在web.config中設定了Authority。我們從open-id提供程式配置資訊url中獲取金鑰。然後,我們將使用此金鑰在每個請求上驗證令牌。我們使用Microsoft System.IdentityModel.Tokens.Jwt包來驗證JWT令牌。最後,我們只需要在web.config中註冊此HttpModule,
1 |
< system.webServer > |
2 |
< modules > |
3 |
< add name = "JsonWebTokenHttpModule" type = "AspNetWebFormsWithIdentityServer3.JsonWebTokenHttpModule" /> |
4 |
</ modules > |
5 |
</ system.webServer > |
新增並註冊上述HttpModule後,我們所有的web.config授權都可以按預期工作。在某些應用程式中,我們使用Microsoft.Owin.Security.OpenIdConnect和IdentityServer3.AccessTokenValidation來驗證訪問令牌。
https://weblogs.asp.net/imranbaloch/aspnet-webforms-identityserver3
摘要:
在本文中,我向您展示了我們如何輕鬆驗證獨立的Json Web令牌並在ASP.NET Web窗體中設定使用者身份。您可以在github上找到原始碼。