- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章详解ASP.NET Core Token认证由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
令牌认证(Token Authentication)已经成为单页应用(SPA)和移动应用事实上的标准。即使是传统的B/S应用也能利用其优点。优点很明白:极少的服务端数据管理、可扩展性、可以使用单独的认证服务器和应用服务器分离.
如果你对令牌(token)不是太了解,可以看这篇文章( overview of token authentication and JWTs) 。
令牌认证在asp.net core中集成。其中包括保护Bearer Jwt的路由功能,但是移除了生成token和验证token的部分,这些可以自定义或者使用第三方库来实现,得益于此,MVC和Web api项目可以使用令牌认证,而且很简单。下面将一步一步实现,代码可以在( 源码)下载.
ASP.NET Core令牌验证 。
首先,背景知识:认证令牌,例如JWTs,是通过http 认证头传递的,例如:
1
2
|
GET /foo
Authorization: Bearer [token]
|
令牌可以通过浏览器cookies。传递方式是header或者cookies取决于应用和实际情况,对于移动app,使用headers,对于web,推荐在html5 storage中使用cookies,来防止xss攻击.
asp.net core对jwts令牌的验证很简单,特别是你通过header传递.
1、生成 SecurityKey,这个例子,我生成对称密钥验证jwts通过HMAC-SHA256加密方式,在startup.cs中:
1
2
3
|
// secretKey contains a secret passphrase only your server knows
var secretKey =
"mysupersecret_secretkey!123"
;
var signingKey =
new
SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretKey));
|
验证 header中传递的JWTs 。
在 Startup.cs中,使用Microsoft.AspNetCore.Authentication.JwtBearer中的UseJwtBearerAuthentication 方法获取受保护的api或者mvc路由有效的jwt.
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
|
var tokenValidationParameters =
new
TokenValidationParameters
{
// The signing key must match!
ValidateIssuerSigningKey =
true
,
IssuerSigningKey = signingKey,
// Validate the JWT Issuer (iss) claim
ValidateIssuer =
true
,
ValidIssuer =
"ExampleIssuer"
,
// Validate the JWT Audience (aud) claim
ValidateAudience =
true
,
ValidAudience =
"ExampleAudience"
,
// Validate the token expiry
ValidateLifetime =
true
,
// If you want to allow a certain amount of clock drift, set that here:
ClockSkew = TimeSpan.Zero
};
app.UseJwtBearerAuthentication(
new
JwtBearerOptions
{
AutomaticAuthenticate =
true
,
AutomaticChallenge =
true
,
TokenValidationParameters = tokenValidationParameters
});
|
通过这个中间件,任何[Authorize]的请求都需要有效的jwt:
签名有效; 。
过期时间; 。
有效时间; 。
Issuer 声明等于“ExampleIssuer” 。
订阅者声明等于 “ExampleAudience” 。
如果不是合法的JWT,请求终止,issuer声明和订阅者声明不是必须的,它们用来标识应用和客户端.
在cookies中验证JWTs 。
ASP.NET Core中的cookies 认证不支持传递jwt。需要自定义实现 ISecureDataFormat接口的类。现在,你只是验证token,不是生成它们,只需要实现Unprotect方法,其他的交给System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler这个类处理.
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
|
using
System;
using
System.IdentityModel.Tokens.Jwt;
using
System.Security.Claims;
using
Microsoft.AspNetCore.Authentication;
using
Microsoft.AspNetCore.Http.Authentication;
using
Microsoft.IdentityModel.Tokens;
namespace
SimpleTokenProvider
{
public
class
CustomJwtDataFormat : ISecureDataFormat<AuthenticationTicket>
{
private
readonly
string
algorithm;
private
readonly
TokenValidationParameters validationParameters;
public
CustomJwtDataFormat(
string
algorithm, TokenValidationParameters validationParameters)
{
this
.algorithm = algorithm;
this
.validationParameters = validationParameters;
}
public
AuthenticationTicket Unprotect(
string
protectedText)
=> Unprotect(protectedText,
null
);
public
AuthenticationTicket Unprotect(
string
protectedText,
string
purpose)
{
var handler =
new
JwtSecurityTokenHandler();
ClaimsPrincipal principal =
null
;
SecurityToken validToken =
null
;
try
{
principal = handler.ValidateToken(protectedText,
this
.validationParameters,
out
validToken);
var validJwt = validToken
as
JwtSecurityToken;
if
(validJwt ==
null
)
{
throw
new
ArgumentException(
"Invalid JWT"
);
}
if
(!validJwt.Header.Alg.Equals(algorithm, StringComparison.Ordinal))
{
throw
new
ArgumentException($
"Algorithm must be '{algorithm}'"
);
}
// Additional custom validation of JWT claims here (if any)
}
catch
(SecurityTokenValidationException)
{
return
null
;
}
catch
(ArgumentException)
{
return
null
;
}
// Validation passed. Return a valid AuthenticationTicket:
return
new
AuthenticationTicket(principal,
new
AuthenticationProperties(),
"Cookie"
);
}
// This ISecureDataFormat implementation is decode-only
public
string
Protect(AuthenticationTicket data)
{
throw
new
NotImplementedException();
}
public
string
Protect(AuthenticationTicket data,
string
purpose)
{
throw
new
NotImplementedException();
}
}
}
|
在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
|
var tokenValidationParameters =
new
TokenValidationParameters
{
// The signing key must match!
ValidateIssuerSigningKey =
true
,
IssuerSigningKey = signingKey,
// Validate the JWT Issuer (iss) claim
ValidateIssuer =
true
,
ValidIssuer =
"ExampleIssuer"
,
// Validate the JWT Audience (aud) claim
ValidateAudience =
true
,
ValidAudience =
"ExampleAudience"
,
// Validate the token expiry
ValidateLifetime =
true
,
// If you want to allow a certain amount of clock drift, set that here:
ClockSkew = TimeSpan.Zero
};
app.UseCookieAuthentication(
new
CookieAuthenticationOptions
{
AutomaticAuthenticate =
true
,
AutomaticChallenge =
true
,
AuthenticationScheme =
"Cookie"
,
CookieName =
"access_token"
,
TicketDataFormat =
new
CustomJwtDataFormat(
SecurityAlgorithms.HmacSha256,
tokenValidationParameters)
});
|
如果请求中包含名为access_token的cookie验证为合法的JWT,这个请求就能返回正确的结果,如果需要,你可以加上额外的jwt chaims,或者复制jwt chaims到ClaimsPrincipal在CustomJwtDataFormat.Unprotect方法中,上面是验证token,下面将在asp.net core中生成token.
ASP.NET Core生成Tokens 。
在asp.net 4.5中,这个UseOAuthAuthorizationServer中间件可以轻松的生成tokens,但是在asp.net core取消了,下面写一个简单的token生成中间件,最后,有几个现成解决方案的链接,供你选择.
简单的token生成节点 。
首先,生成 POCO保存中间件的选项. 生成类:TokenProviderOptions.cs 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
using
System;
using
Microsoft.IdentityModel.Tokens;
namespace
SimpleTokenProvider
{
public
class
TokenProviderOptions
{
public
string
Path {
get
;
set
; } =
"/token"
;
public
string
Issuer {
get
;
set
; }
public
string
Audience {
get
;
set
; }
public
TimeSpan Expiration {
get
;
set
; } = TimeSpan.FromMinutes(5);
public
SigningCredentials SigningCredentials {
get
;
set
; }
}
}
|
现在自己添加一个中间件,asp.net core 的中间件类一般是这样的:
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
|
using
System.IdentityModel.Tokens.Jwt;
using
System.Security.Claims;
using
System.Threading.Tasks;
using
Microsoft.AspNetCore.Http;
using
Microsoft.Extensions.Options;
using
Newtonsoft.Json;
namespace
SimpleTokenProvider
{
public
class
TokenProviderMiddleware
{
private
readonly
RequestDelegate _next;
private
readonly
TokenProviderOptions _options;
public
TokenProviderMiddleware(
RequestDelegate next,
IOptions<TokenProviderOptions> options)
{
_next = next;
_options = options.Value;
}
public
Task Invoke(HttpContext context)
{
// If the request path doesn't match, skip
if
(!context.Request.Path.Equals(_options.Path, StringComparison.Ordinal))
{
return
_next(context);
}
// Request must be POST with Content-Type: application/x-www-form-urlencoded
if
(!context.Request.Method.Equals(
"POST"
)
|| !context.Request.HasFormContentType)
{
context.Response.StatusCode = 400;
return
context.Response.WriteAsync(
"Bad request."
);
}
return
GenerateToken(context);
}
}
}
|
这个中间件类接受TokenProviderOptions作为参数,当有请求且请求路径是设置的路径(token或者api/token),Invoke方法执行,token节点只对 POST请求而且包括form-urlencoded内容类型(Content-Type: application/x-www-form-urlencoded),因此调用之前需要检查下内容类型.
最重要的是GenerateToken,这个方法需要验证用户的身份,生成jwt,传回jwt:
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
|
private
async Task GenerateToken(HttpContext context)
{
var username = context.Request.Form[
"username"
];
var password = context.Request.Form[
"password"
];
var identity = await GetIdentity(username, password);
if
(identity ==
null
)
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync(
"Invalid username or password."
);
return
;
}
var now = DateTime.UtcNow;
// Specifically add the jti (random nonce), iat (issued timestamp), and sub (subject/user) claims.
// You can add other claims here, if you want:
var claims =
new
Claim[]
{
new
Claim(JwtRegisteredClaimNames.Sub, username),
new
Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new
Claim(JwtRegisteredClaimNames.Iat, ToUnixEpochDate(now).ToString(), ClaimValueTypes.Integer64)
};
// Create the JWT and write it to a string
var jwt =
new
JwtSecurityToken(
issuer: _options.Issuer,
audience: _options.Audience,
claims: claims,
notBefore: now,
expires: now.Add(_options.Expiration),
signingCredentials: _options.SigningCredentials);
var encodedJwt =
new
JwtSecurityTokenHandler().WriteToken(jwt);
var response =
new
{
access_token = encodedJwt,
expires_in = (
int
)_options.Expiration.TotalSeconds
};
// Serialize and return the response
context.Response.ContentType =
"application/json"
;
await context.Response.WriteAsync(JsonConvert.SerializeObject(response,
new
JsonSerializerSettings { Formatting = Formatting.Indented }));
}
|
大部分代码都很官方,JwtSecurityToken 类生成jwt,JwtSecurityTokenHandler将jwt编码,你可以在claims中添加任何chaims。验证用户身份只是简单的验证,实际情况肯定不是这样的,你可以集成 identity framework或者其他的,对于这个实例只是简单的硬编码:
1
2
3
4
5
6
7
8
9
10
11
|
private
Task<ClaimsIdentity> GetIdentity(
string
username,
string
password)
{
// DON'T do this in production, obviously!
if
(username ==
"TEST"
&& password ==
"TEST123"
)
{
return
Task.FromResult(
new
ClaimsIdentity(
new
System.Security.Principal.GenericIdentity(username,
"Token"
),
new
Claim[] { }));
}
// Credentials are invalid, or account doesn't exist
return
Task.FromResult<ClaimsIdentity>(
null
);
}
|
添加一个将DateTime生成timestamp的方法:
1
2
|
public
static
long
ToUnixEpochDate(DateTime date)
=> (
long
)Math.Round((date.ToUniversalTime() -
new
DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero)).TotalSeconds);
|
现在,你可以将这个中间件添加到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
42
43
44
45
46
47
48
49
50
51
52
53
54
|
using
System.Text;
using
Microsoft.AspNetCore.Builder;
using
Microsoft.AspNetCore.Hosting;
using
Microsoft.Extensions.Configuration;
using
Microsoft.Extensions.DependencyInjection;
using
Microsoft.Extensions.Logging;
using
Microsoft.Extensions.Options;
using
Microsoft.IdentityModel.Tokens;
namespace
SimpleTokenProvider
{
public
partial
class
Startup
{
public
Startup(IHostingEnvironment env)
{
var builder =
new
ConfigurationBuilder()
.AddJsonFile(
"appsettings.json"
, optional:
true
);
Configuration = builder.Build();
}
public
IConfigurationRoot Configuration {
get
;
set
; }
public
void
ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
// The secret key every token will be signed with.
// In production, you should store this securely in environment variables
// or a key management tool. Don't hardcode this into your application!
private
static
readonly
string
secretKey =
"mysupersecret_secretkey!123"
;
public
void
Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(LogLevel.Debug);
loggerFactory.AddDebug();
app.UseStaticFiles();
// Add JWT generation endpoint:
var signingKey =
new
SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretKey));
var options =
new
TokenProviderOptions
{
Audience =
"ExampleAudience"
,
Issuer =
"ExampleIssuer"
,
SigningCredentials =
new
SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256),
};
app.UseMiddleware<TokenProviderMiddleware>(Options.Create(options));
app.UseMvc();
}
}
}
|
测试一下,推荐使用chrome 的postman:
1
2
3
|
POST /token
Content-Type: application/x-www-form-urlencoded
username=TEST&password=TEST123
|
结果: OK 。
Content-Type: application/json { "access_token": "eyJhb...", "expires_in": 300 } 。
你可以使用jwt工具查看生成的jwt内容。如果开发的是移动应用或者单页应用,你可以在后续请求的header中存储jwt,如果你需要在cookies中存储的话,你需要对代码修改一下,需要将返回的jwt字符串添加到cookie中。 测试下:
其他方案 。
下面是比较成熟的项目,可以在实际项目中使用:
下面的文章可以让你更加的了解认证:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.
原文链接:http://www.cnblogs.com/indexlang/p/indexlang.html 。
最后此篇关于详解ASP.NET Core Token认证的文章就讲到这里了,如果你想了解更多关于详解ASP.NET Core Token认证的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在使用 Tornado 与 twitter 等第三方进行身份验证。 我的登录处理程序看起来像这样 class AuthLoginHandler(BaseHandler, tornado.auth.
有没有一种真正的方法可以在 Pylons 中添加身份验证?我见过很多不同的方法,但大多数方法要么过时,要么过于复杂。是否有教程可以解释如何以良好而可靠的方式添加身份验证? 最佳答案 考虑使用 repo
RESTful 身份验证是什么意思,它是如何工作的?我在谷歌上找不到很好的概述。我唯一的理解是您在 URL 中传递了 session key (记住),但这可能是非常错误的。 最佳答案 如何在 RES
我正在考虑在基于插件的系统中实现安全性的多种方式。现在,当我说“安全”时,我的意思是: a) 插件系统的开发人员如何确保插件在核心平台上的使用是安全的。b) 插件开发人员如何确保在其平台上使用的插件是
我正在使用 WCF Webhttp 服务。我创建了一堆服务,剩下的就是放入用户身份验证... 问题 与其余架构风格保持一致,我是否应该针对用户 db 验证每个服务调用。 如果是这样,我应该在每次调用服
假设我想对 Mifare Classic 进行身份验证。 我如何知道要发送到卡的确切类型的 APDU? 例子。 这段代码: bcla = 0xFF; bins = 0x86; bp1 = 0x0;
我通过在文件 xyz.php 中编写以下代码登录到网站。当我运行这个文件时,我会登录到 moodle 网站。有什么方法可以像下面的登录代码一样注销吗? $user = authenticate_use
我有一个应用程序可以匿名访问除几个之外的所有 xpages。我需要强制用户登录这些 xpages。是使用 beforepageload 事件来检查用户登录页面并将其重定向到正确的方式还是有更好的方法?
我想用 ember.js 实现身份验证。 因此,当应用程序启动时,在路由器处理请求的 url 之前,我想检查用户状态。如果用户未通过身份验证,我想保存请求的 url 并重定向到特定的 url (/lo
您如何执行 jQuery Ajax 调用并在发送请求之前对调用进行身份验证? 我还没有登录所以必须进行身份验证。安全不是任何人都可以访问的问题,只需要进行身份验证。它只是基本的 http 身份验证,您
我尝试使用找到的 swift 代码 here在网站上找到here ,但响应是带有两个错误的 html 代码:“您必须输入密码!”和“您必须输入用户名!”我是 NSURLSession 的新手,并尝试更
我正在尝试连接到 Visa Direct API,但我没有通过基本的 SSL 证书认证,这是我的代码: import requests headers = { 'Content
我正在用 tornado 在 python 中开发一个 REST API,我将实现身份验证和授权,试图避免锁定到其他大项目,即 django。我也在通过论坛和 SO 环顾四周,我喜欢一个可能适合的解决
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭10
如何在 Android 中通过 HTTP 进行身份验证? 最佳答案 我非常难以在 Android 中通过 HTTP 进行身份验证,因为在浏览器(Web 和 Android native )中它工作完美
我有一些关于登录和 session 的问题。我有这段代码: 数据库查询: login: function(req,callback) { var query = 'SELECT id FROM
我开始使用 Swift 开发 iOS 应用。现在我正处于需要创建登录系统的部分。但是,我们需要人们提供的 LinkedIn 信息。 我如何在 iOS 中使用 OAuth2 API 来实现这一点? 我已
如果没有找到用户,问题出在每个 $routeChangeStart 上,如果我只输入 url,它仍然会引导我访问页面。 现在我已经在服务器上重写了规则。 Options +FollowSymlinks
简单代码 require 'net/http' url = URI.parse('get json/other data here [link]') req = Net::HTTP::Get.new(
参考文档: https://docs.sonarqube.org/latest/instance-administration/security/ 概述 SonarQube具有
我是一名优秀的程序员,十分优秀!