天天看點

NetCore配置使用

作者:中年農碼工

什麼是JWT(詳情在面試.md中有)

JWT是目前最流行的跨域身份驗證解決方案,JWT的原則是在伺服器身份驗證之後,會傳回一個Json資料,,之後,當使用者與伺服器通信的時候,客戶在請求中發揮Json對象,伺服器會根據這個json對象來判斷使用者的身份,.為了防止使用者篡改資訊,伺服器會在生成對象的時候加上一段簽名,

伺服器不會儲存任何資料,處于無狀态,變得更容易擴充

2、完整的JWT由三分部段落, 每個段由英文(.)連接配接

3、分别Header(頭部)、Payload(載荷)、signature(簽名)

第一步.Net 6環境下在Nuget安裝JWT以及*Microsoft.AspNetCore.Authentication.JwtBearer**

NetCore配置使用

第二步,在appsettings.json配置相關配置

"Authentication": {
"SecretKey": "nadjhfgkadshgoihfkajhkjdhsfaidkuahfhdksjaghidshyaukfhdjks",//密鑰
"Issuer": "www.adsfsadfasdf",//注冊人
"Audience": "www.adsfsadfasdf"//通路人
}
           

第三步,在Program.cs中注冊

builder.Services.AddSwaggerGen(c => {

//開啟Swagger注釋

    var xmlFile = #34;{Assembly.GetExecutingAssembly().GetName().Name}.xml";
​    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
​    c.IncludeXmlComments(xmlPath, true);

//在Swagger上顯示可調試

​    var scheme = new OpenApiSecurityScheme()
​    {
​        Description = "Authorization header. \r\nExample: 'Bearer 12345abcdef'",
​        Reference = new OpenApiReference
​        {
​            Type = ReferenceType.SecurityScheme,
​            Id = "Authorization"
​        },
​        Scheme = "oauth2",
​        Name = "Authorization",
​        In = ParameterLocation.Header,
​        Type = SecuritySchemeType.ApiKey,
​    };
​    c.AddSecurityDefinition("Authorization", scheme);
​    var requirement = new OpenApiSecurityRequirement();
​    requirement[scheme] = new List<string>();
​    c.AddSecurityRequirement(requirement);
});

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
    //取出私鑰
    var secretByte = Encoding.UTF8.GetBytes(builder.Configuration["Authentication:SecretKey"]);
    options.TokenValidationParameters = new TokenValidationParameters()
    {
        //驗證釋出者
        ValidateIssuer = true,
        ValidIssuer = builder.Configuration["Authentication:Issuer"],
        //驗證接收者
        ValidateAudience = true,
        ValidAudience = builder.Configuration["Authentication:Audience"],
        //驗證是否過期
        ValidateLifetime = true,
        //驗證私鑰
        IssuerSigningKey = new SymmetricSecurityKey(secretByte)
    };
});

//注冊(單例模式)

builder.Services.AddSingleton(typeof(JwtSecurityTokenHandler));
builder.Services.AddSingleton(typeof(TokenHelper));

//中間件(開啟)

//鑒權
app.UseAuthentication();
//授權
app.UseAuthorization();

//通路所有API.需要jwt驗證通過才可以

app.MapControllers().RequireAuthorization();
           

第四步,定義注冊存入TokenHelper類,友善對JWT令牌進行管理,實作接口:

public class TokenHelper
    {
        private readonly IConfiguration _configuration;
        private readonly JwtSecurityTokenHandler _jwtSecurityTokenHandler;
        public TokenHelper(IConfiguration configuration, JwtSecurityTokenHandler jwtSecurityTokenHandler)
        {
            _configuration = configuration;
            _jwtSecurityTokenHandler = jwtSecurityTokenHandler;
        }
        /// <summary>
        /// 建立加密JwtToken
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public string CreateJwtToken<T>(T user)
        {
            var signingAlogorithm = SecurityAlgorithms.HmacSha256;
            var claimList = this.CreateClaimList(user);
            //Signature
            //取出私鑰并以utf8編碼位元組輸出
            var secretByte = Encoding.UTF8.GetBytes(_configuration["Authentication:SecretKey"]);
            //使用非對稱算法對私鑰進行加密
            var signingKey = new SymmetricSecurityKey(secretByte);
            //使用HmacSha256來驗證加密後的私鑰生成數字簽名
            var signingCredentials = new SigningCredentials(signingKey, signingAlogorithm);
            //生成Token
            var Token = new JwtSecurityToken(
          issuer: _configuration["Authentication:Issuer"], //釋出者
            audience: _configuration["Authentication:Audience"], //接收者
            claims: claimList, //存放的使用者資訊
            notBefore: DateTime.UtcNow, //釋出時間
            expires: DateTime.UtcNow.AddDays(1), //有效期設定為1天
            signingCredentials //數字簽名
            );
            //生成字元串token
            var TokenStr = new JwtSecurityTokenHandler().WriteToken(Token);
            return TokenStr;
        }
           
public T GetToken<T>(string Token)
    {
        Type t = typeof(T);

        object objA = Activator.CreateInstance(t);
        var b = _jwtSecurityTokenHandler.ReadJwtToken(Token);
        foreach (var item in b.Claims)
        {
            PropertyInfo _Property = t.GetProperty(item.Type);
            if (_Property != null && _Property.CanRead)
            {
                _Property.SetValue(objA, item.Value, null);
            }

        }
        return (T)objA;
    }
    /// <summary>
    /// 建立包含使用者資訊的CalimList
    /// </summary>
    /// <param name="authUser"></param>
    /// <returns></returns>
    private List<Claim> CreateClaimList<T>(T authUser)
    {
        var Class = typeof(UserDto);
        List<Claim> claimList = new List<Claim>();
        //foreach (var item in Class.GetProperties())
        //{
        //    if (item.Name == "UPass")
        //    {
        //        continue;
        //    }
        //    claimList.Add(new Claim(item.Name, Convert.ToString(item.GetValue(authUser))));
        //}
        claimList.Add(new Claim("Id", Convert.ToString(authUser)));
        return claimList;
    }
           

在控制器中的實作([AllowAnonymous]//允許任何人通路,一般在登入方法上)

private readonly IUserRepository _db;自己的業務層
private readonly TokenHelper _tokenHelper;//兩個必須插入
private readonly JwtSecurityTokenHandler _jwtSecurityTokenHandler;//兩個必須插入
           
public UserController(IUserRepository db, TokenHelper tokenHelper, JwtSecurityTokenHandler jwtSecurityTokenHandler)
    {
        _db = db;
        _tokenHelper = tokenHelper;
        _jwtSecurityTokenHandler = jwtSecurityTokenHandler;
    }
           
/// <summary>
        /// 登入
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        [AllowAnonymous]//允許任何人通路
        [HttpPost]
        public IActionResult Login(string? username, string? password)
        {
            if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
            {
                return BadRequest("賬号或密碼不能為空");
            }
            password= Md5Help.GetMD5Hash(password);
            var list = _db.Login(username, password);
            var result = new ApiResult();
            if (list!=null)
            {
                var Token = Response.Headers["TokenStr"] = _tokenHelper.CreateJwtToken(result);
                Response.Headers["Access-Control-Expose-Headers"] = "TokenStr";
                result.Code = 200;
                result.Msg = "登陸成功";
                result.Data = list;
            }
            else
            {
                result.Code = 500;
                result.Msg = "登陸失敗";
            }
            return Ok(result);

  }
           

Vue中接收使用

第一步:在登入請求成功之後,将token放入localstory中(token可以在res中檢視,一般都在res.headers.tokenstr,可打斷點檢視res)

window.localStorage.setItem("UserToker", res.headers.tokenstr);
           

第二步:自定義檔案(main.js中簡易使用方法)不建議使用

//請求攔截器

axios.interceptors.request.use(function (config) {

 // Do something before request is sent

 let token = localStorage.getItem('UserToker')

 if (token != null) {

  //将token 放到你的請求頭上

  config.headers.Authorization = 'Bearer ' + token;

 }



 return config;

}, function (error) {

 // Do something with request error

 return Promise.reject(error);

});
           

推薦使用方法:*攔截器+統一所有請求頭中包含token,建立檔案http.js與main.js同級*

import axios from 'axios'

// 攔截器
const service = axios.create({
 // timeout:10000
 baseURL:"http://localhost:44320/" //這裡寫自己的api位址
})

// 統一所有請求頭中包含token
var t =  window.sessionStorage.getItem('token');
if(t===null || t.length===0 || t==undefined)
{
 t='';
}
service.defaults.headers.common['Authorization']=t;

export default service;
           

main.js配置

2、配置main.js,添加以下代碼,在 Vue.config.productionTip = false 下面

import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.use(ElementUI);

import axios from './http'
Vue.prototype.$http = axios
import VueAxios from 'vue-axios'

Vue.use(VueAxios)           

繼續閱讀