ASP.NET Core生成,校驗jwt的(accessToken)訪問令牌和(refreshToken)刷新令牌示例講解


ASP.NET Core生成,校驗jwt的(accessToken)訪問令牌和(refreshToken)刷新令牌示例講解

-懶狗如我,解析都寫到注釋里了,寫的很詳細,不懂的地方翻翻文檔

微軟文檔

using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using jwt.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;

namespace jwtTest.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class SignInController : Controller
    {
        private IConfiguration _configuration { get; set; }

        // 控制器注入Configuration依賴,方便獲取appsettinfs.json中的SecurityKey
        public SignInController(IConfiguration config)
        {
            _configuration = config;
        }


        [HttpGet("login")]
        public ActionResult Login(string username, string password)//應該寫個LoginDto,我懶了
        {
            if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
            {
                var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();

                //在此進行賬號密碼認證,此代碼省略

                //------------生成AccessToken----------------------------------
                // token中的claims用於儲存自定義信息,如登錄之后的用戶id等
                var claims = new[]
                {
                    new Claim("username",username),
                    new Claim("password",password),//演示用,(不要把密碼寫進token啊喂!!!(#`O′))
                    //new Claim(ClaimTypes.Role,"admin")
                    new Claim("role","admin")//此寫法和上面寫法效果一樣
                };
                // 獲取SecurityKey
                var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("myJWTKeyasasasasa"));
                //生成Token
                var token = new JwtSecurityToken(
                    issuer: "cxy",                    // 發布者
                    audience: "myClient",                // 接收者
                    notBefore: DateTime.Now,                                                          // token簽發時間
                    expires: DateTime.Now.AddMinutes(30),                                             // token過期時間
                    claims: claims,                                                                   // 該token內存儲的自定義字段信息
                    signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)    // 用於簽發token的秘鑰算法
                );
                //-----------下面是生成RefreshToken--------------------------
                var refClaims = new[]
               {
                    new Claim("role","refresh")
                };
                var refreshToken = new JwtSecurityToken(
                    issuer: "cxy",                    // 發布者
                    audience: "myClient",                // 接收者
                    notBefore: DateTime.Now,                                                          // token簽發時間
                    expires: DateTime.Now.AddDays(7),                                             // token過期時間
                    claims: refClaims,                                                                   // 該token內存儲的自定義字段信息
                    signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)    // 用於簽發token的秘鑰算法
                );

                // 返回成功信息,寫出token
                return Ok(new { code = 200, message = "登錄成功", accessToken = jwtSecurityTokenHandler.WriteToken(token), refreshToken = jwtSecurityTokenHandler.WriteToken(refreshToken) });
            }
            // 返回錯誤請求信息
            return BadRequest(new { code = 400, message = "登錄失敗,用戶名或密碼為空" });
        }







        //此方法用來刷新令牌,邏輯是驗證refToken才能進入方法,進入后驗證accessToken除了過期時間項的其他所有項,目的是防止用戶修改權限等
        [HttpPost("refresh")]
        [Authorize(Roles = "refresh")]//驗證權限
        public ActionResult Refresh(RefreshDto refreshDto)
        {
            var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();//這個類是老朋友了

            bool isCan =jwtSecurityTokenHandler.CanReadToken(refreshDto.AccessToken);//驗證Token格式
            if (!isCan)
                return BadRequest(new { code = 400, message = "傳入訪問令牌格式錯誤" });
            //var jwtToken = jwtSecurityTokenHandler.ReadJwtToken(refreshDto.AccessToken);//轉換類型為token,不用這一行


           
            
            var validateParameter = new TokenValidationParameters()//驗證參數
            {
                ValidateAudience = true,
                // 驗證發布者
                ValidateIssuer = true,
                // 驗證過期時間
                ValidateLifetime = false,
                // 驗證秘鑰
                ValidateIssuerSigningKey = true,
                // 讀配置Issure
                ValidIssuer = "cxy",
                // 讀配置Audience
                ValidAudience = "myClient",
                // 設置生成token的秘鑰
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("myJWTKeyasasasasa"))
            };

            //驗證傳入的過期的AccessToken
            SecurityToken validatedToken = null;
            try
            {
                jwtSecurityTokenHandler.ValidateToken(refreshDto.AccessToken, validateParameter,out validatedToken);//微軟提供的驗證方法。那個out傳出的參數,類型是是個抽象類,記得轉換
            }
            catch(SecurityTokenException)
            {
                return BadRequest(new {code=400, message= "傳入AccessToken被修改" });
            }
           



            // 獲取SecurityKey
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("myJWTKeyasasasasa"));//不要學我寫這里啊,我是懶狗,寫appsettings.json這里去,寫到類的屬性里,注入一下

            var refClaims = new[]
                {
                    new Claim("role","refresh")
                };
            var refreshToken = new JwtSecurityToken(
                issuer: "cxy",                    // 發布者
                audience: "myClient",                // 接收者
                notBefore: DateTime.Now,                                                          // token簽發時間
                expires: DateTime.Now.AddDays(7),                                             // token過期時間
                claims: refClaims,                                                                   // 該token內存儲的自定義字段信息
                signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)    // 用於簽發token的秘鑰算法
            );

            var jwtToken = validatedToken as JwtSecurityToken;//轉換一下
            var accClaims = jwtToken.Claims;
            var accessToken = new JwtSecurityToken(
                    issuer: "cxy",                    // 發布者
                    //audience: "myClient",                // 接收者
                    notBefore: DateTime.Now,                                                          // token簽發時間
                    expires: DateTime.Now.AddMinutes(30),                                             // token過期時間
                    claims: accClaims,                                                                   // 該token內存儲的自定義字段信息
                    signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)    // 用於簽發token的秘鑰算法
                );


            // 返回成功信息,寫出token
            return Ok(new {
                code = 200, message = "令牌刷新成功", refreshToken =jwtSecurityTokenHandler.WriteToken(refreshToken), accessToken =new JwtSecurityTokenHandler().WriteToken(accessToken)
            });
        }
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM