記事のディレクトリ
JWT簡単
JWTは何ですか
(JWT)トークンJSONウェブは、オープンスタンダードに基づいたネットワークアプリケーション実行環境の間を通過するために文をあるJSON((7519 RFC)。トークンは、コンパクトで安全な、特にシングルに分散したサイトのためになるように設計されてサインオン(SSO)シナリオ.JWT文は一般的に提供するために使用されており、サービスプロバイダは、サーバからリソースを取得するために識別情報を認証されたユーザ識別情報との間で転送し、あなたもでなければならないいくつかの余分な他のビジネス・ロジックを追加することができます、トークンは直接認証に使用することができますステートメント情報は暗号化されてもよいです。
兄下からジェーンの本の上に、あなたがそれを読んで持っているピアを強くお勧めします。
著者:Dearmadman
リンク:HTTPS://www.jianshu.com/p/576dbf44b2ae
頭(ヘッダ)、ペイロード(ペイロード)、ビザ情報(署名):JWT 3つの情報、すなわち、で構成される。接続されている三つのか、暗号化アルゴリズムとヘッドの複数の部分と宣言されている「」はJWT文字列になりました。
ヘッドは、情報文でJWT暗号化アルゴリズムですステートメントと宣言を格納しています。
ユーザーに、当社のサーバ負荷情報を保存し、通常のユーザーとトークンの識別有効なGUIDの特定の情報を割り当てられました。
保存されたビザの情報は、直接でASP.Netコアで既製のメソッドを生成する呼び出すことができ、暗号化アルゴリズム情報に関連しています。
それは安全なJWT
まず第一には、ビューのサーバーの観点から、JWTサーバ自体は長い間、ログイントークン缶リクエストフォージェリの傍受などのような特定のユーザのログイントークン、ある関係なく、識別するための、から作られています。
クライアントの観点から、これはリクエストヘッダHTTPリクエストに逃げるために、非パブリックインターフェイスをもたらすために、負荷情報の内部取得トークン解析用データを取得していない場合、単なる文字列トークンのログインです。クライアントは、ビザ情報JWTでもない限り、あなたはまた、独自の有効なトークンを生成しますが、クライアントにビザの情報を保持するにはあまりにも危険なことができます。
そこで、我々は、ログオントークン、これを行うために傍受することができますか?HTTPリクエスト、そして、できる場合にも容易にクロールが、単純ではない場合、範囲、HTTPS暗号化を使用すると、URLの形態であることができるトークンを渡さない限り、リクエストヘッダとボディを含めることであるため、要求は、HTTPSの場合暗号化します。だから、JWTかがhttpsと組み合わせて使用する必要がありますが、これらは抗抗悪役の紳士ではない、ネットワーク伝送に何かが絶対に安全にすることはできません。
JWTでのASP.NETコアで
認可と認証
コードの前に、いくつかの概念を明確に理解する必要がありますがあります。承認(認証)と認証(認証)の概念が理解されなければなりません。これら二つのことは、区別することは本当に難しい見ていない、認証の初め、エンドションです。
非パブリックインターフェイスへのアクセスが最初に認定されている必要があり、その後、許可を検証する前に、まず、。例えば、認証はゲーム内のログのようなものですが、ゲームでは、認可の確認を通過するVIPの特権を使用することはできません。ちょうどあなたが正当なユーザではなく、すべてのユーザーが認証(認証)を必要とする、このアクションを実行する権限を持っていることを示すために認証(認証)。
非パブリックインターフェイスの場合、そこ認証でなければなりませんが、(何のVIPの選手もそれをしない画像を磨くことはできません?)認可する必要はありません。
スリーステップのコード例
ASP.Netコア2.2は、次の3つの手順でJWT認証を使用しています。
何のカスタム許可および認証は、第二段階を無視することはできません場合。
JWTを生成します
すべての非パブリックインターフェイスへのアクセスは、トークンによってユーザーを識別した後、まず、我々は成功しJWTユーザーがログイン後に編集するにはログインインタフェースを必要とするが、彼にトークンを与えます。GUIDを取得したユーザ情報に基づいて、後続の操作をトークンは、それに関連付けられたGUID、のGUIDレコードが含まれており、ユーザーのログイン情報が成功しています。
[HttpPost("login")]
public IActionResult Login([FromBody]Client user)
{
IActionResult ret = null; // 用户登录验证
if(CheckUser(user))
{
// 验证通过,生成唯一识别码放到Token的Payload(载荷)里面
string guid = Guid.NewGuid().ToString();
List<Claim> payloadList = new List<Claim>();
payloadList.Add(new Claim("Guid", guid));
// payloadList.Add(new Claim("Other", data)); // 根据需要继续添加
Claim[] payload = payloadList.ToArray();
string securityKey = _configuration["SecurityKey"];
// sign the token using a secret key.This secret will be shared between your API and anything that needs to check that the token is legit.
// 读取配置文件中的秘钥
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityKey));
// 设置加密算法(签证信息)
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
// 把设置填到token里(这里我省略了发布者和使用者的验证)
JwtSecurityToken token = new JwtSecurityToken(
claims: payload, // payload
signingCredentials: creds, // 签证信息
expires: DateTime.Now.AddMinutes(60)); // 过期时间
string tokenStr = new JwtSecurityTokenHandler().WriteToken(token);
// 把该用户和该Token中的guid关联起来,其他接口根据Token中的guid获取用户信息
SetUserGuid(user, guid);
// 回送Token和有效时长
ret = Ok(new { Token = tokenStr, Expire = 60 }); //做回送
}
else
{
ret = BadRequest();
}
return ret;
}
編集承認ポリシー
それは戦略が承認クラスの条件を検証するために必要とされ、二つのクラス、1クラスの認可検証戦略を作成する必要があります。
そこを理解していないが、Microsoftの公式ドキュメントを表示することをお勧めします。
https://docs.microsoft.com/zh-cn/aspnet/core/security/authorization/iauthorizationpolicyprovider?view=aspnetcore-2.2
説明、ここClientクラスは、独自のユーザー・クラス、ユーザー名とパスワードか何かを書くことです。
直接禁止(呼び出し指定方法にリダイレクト統一認証失敗)した後、403エラーコードを返します。
/// <summary>
/// 授权验证策略条件(可以理解为验证该授权需要的东西)
/// </summary>
public class PermissionRequirement : IAuthorizationRequirement
{
public bool CheckPermission(Client user)
{
bool ret = true;
// 检查用户权限
// Coding...
return ret;
}
}
/// <summary>
/// 授权验证策略
/// </summary>
public class TokenPolicy : AuthorizationHandler<PermissionRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
{
var httpContext = (context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext).HttpContext;
string guid = "";
if (httpContext.User.Identity.IsAuthenticated)
{
var auth = httpContext.AuthenticateAsync().Result.Principal.Claims;
var guidClaim = auth.FirstOrDefault(s => s.Type == "Guid");
if (guidClaim != null)
{
guid = guidClaim.Value;
// 根据Guid获取用户信息(该方法是自己编写的)
if (GetUserByGuid(guid, out Client user))
{
// 验证成功且拥有权限
if(requirement.CheckPermission(user))
{
context.Succeed(requirement);
}
else
{
// 验证成功但权限不足
httpContext.Response.Redirect($"api/identify/forbidden");
}
}
else
{
// 验证成功,但Guid非法
httpContext.Response.Redirect($"api/identify/forbidden");
}
}
else
{
// 验证成功,但没有包含Guid
httpContext.Response.Redirect($"api/identify/forbidden");
}
}
else
{
// 验证失败,没有包含验证信息
httpContext.Response.Redirect($"api/identify/forbidden");
}
return Task.CompletedTask;
}
}
構成でスタートアップ
登録JWT認証と当社独自の認証の検証方法ConfigureServicesメソッド起動クラス。
なしカスタム認可検証する場合は、AddAuthorizationメソッドを呼び出すことはできません。
public void ConfigureServices(IServiceCollection services)
{
// 注册自定义的授权验证方法
services.AddAuthorization(options =>
{
options.AddPolicy("Permission", policy => policy.Requirements.Add(new PermissionRequirement()));
})
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) // 注册Jwt认证
.AddJwtBearer(option =>
{
// 读取配置文件中的秘钥
string securityKey = Config["SecurityKey"];
option.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidateLifetime = true,
ValidateIssuer = false,
ValidateIssuerSigningKey = true,
ValidateAudience = false,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityKey))
};
});
// 不需要自定义授权验证的可以不添加这个单例
services.AddSingleton<IAuthorizationHandler, TokenPolicy>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
最後に、我々のアプローチスタートアップクラスConfigureメソッドを追加します。ここでは、)(再び第1 UseAuthentication()UserMvcに注意しなければなりません
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
app.UseMvc();
}
プロパティを追加します。
ビンの後、我々は、インタフェースまたはコントローラ[承認(「{名前}ライセンス戦略」)]機能を検証する必要性にそれ以上の工程を追加することができます。この種のコントローラまたはインタフェースを自動的に呼び出す前に、JWTの認証および認可ポリシーHandleRequirementAsyncのカスタムメソッドを実行します。
インタフェース方法においてUser.Claims.Firstと(ペイロード)が含まJWT取得load()メソッド
[Authorize("Permission")]
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
//if (User.HasClaim(s => s.Type == "Guid"))
string guid = User.Claims.First(s => s.Type == "Guid").Value;
// 根据guid获取用户信息继续操作
return guid;
}
[承認]特性のないカスタム認証方式を追加していないことは、許可検証戦略を指定しなくても、することができます。
クライアントの使用
テストショット。
ユーザログイン認証後に有効なトークンとJWTの時間を得るために、最初の方式をログインします。
その後、我々は、アクセストークンの検証ルールでインターフェースをしようとする
401のヒントはログインする必要が戻りました。
そして、私たちはもう一度、ヘッダーAuthorizationリクエストへのアクセスを追加し、JWTのトークンを取得しています。
認証ベアラの値はスペースで始まり、その後、ちょうど取得JWTトークンを埋めることをここで注意は、これがデフォルトの内部JWTの検証ルールです。
リクエストが成功しました。
マイクロ流路を用いてアプレット
あなたが時間内にこの期間に追加する何かを持っている場合は、その文字列JWT作られ、アプレット内部util.jsは、時間による更新方法のJWTが必要な場合があります。
// 定时刷新句柄全局变量
var refreshHandle = 0;
function TokenRefresh(min){
refreshHandle = setInterval(function(){
var app = getApp();
var user = app.globalData.userInfo; //保存在全局变量里的用户信息
wx.request({
url: domain + 'values/login',
method: 'POST',
data: user,
dataType: 'json',
responseType: 'text',
success: function (data) {
var result = data.data;
// 登录成功
if (data.statusCode == 200) {
app.globalData.jwtToken = result.token;
}
else{
// 登录失败
}
}
})
},(min-2) * 60 * 1000); // 这里提前两分钟刷新
}
// 用户登出时停止自动刷新
function StopRefresh(){
clearInterval(refreshHandle);
}
ユーザーのログイン方法
UserLogin:function(usrName,psd){
var user = {
UserName: usrName,
Password: psd
}
wx.request({
url: domain + 'values/login',
method: 'POST',
data: user,
dataType: 'json',
responseType: 'text',
success: function (data) {
var result = data.data;
// 登录成功
if (data.statusCode == 200) {
// 有效时间
let expire = result.expire;
// 定时刷新Token
Utils.TokenRefresh(expire);
// 记在全局变量里面
getApp().globalData.jwtToken = result.token;
}
else {
// 登录失败
}
},
fail: function () {
// 连接错误
},
complete: function () {}
})
},
非パブリックインターフェイスへのアクセス
Test:function(){
let token = getApp().globalData.jwtToken;
// 在Header中带上验证信息
var head = {
'content-type': 'application/json;charset=utf-8',
'Authorization': 'Bearer ' + token
}
wx.request({
url: domain + '/values/66',
method: 'GET',
header: head,
dataType: 'json',
responseType: 'text',
success: function (data) {
// Coding
},
fail:function(){ },
complete:function(){ }
})
}
参考資料
Asp.netコア使用JWT
https://www.jianshu.com/p/294ea94f0087
JWT導入
https://www.jianshu.com/p/576dbf44b2ae