草庐IT

JWT(生成Token令牌)

Zhuo-Hu 2023-03-28 原文

.NetCore配置使用

什么是JWT(详情在面试.md中有)

JWT是目前最流行的跨域身份验证解决方案,JWT的原则是在服务器身份验证之后,会返回一个Json数据,,之后,当用户与服务器通信的时候,客户在请求中发挥Json对象,服务器会根据这个json对象来判断用户的身份,.为了防止用户篡改信息,服务器会在生成对象的时候加上一段签名,

服务器不会保存任何数据,处于无状态,变得更容易扩展

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

3、分别Header(头部)、Payload(载荷)、signature(签名)

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

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

"Authentication": {
"SecretKey": "nadjhfgkadshgoihfkajhkjdhsfaidkuahfhdksjaghidshyaukfhdjks",//密钥
"Issuer": "www.adsfsadfasdf",//注册人
"Audience": "www.adsfsadfasdf"//访问人
}

第三步,在Program.cs中注册

builder.Services.AddSwaggerGen(c => {

//开启Swagger注释

​    var xmlFile = $"{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)

有关JWT(生成Token令牌)的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

    在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

  3. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  4. ruby-on-rails - Rails 中的 NoMethodError::MailersController#preview undefined method `activation_token=' for nil:NilClass - 2

    似乎无法为此找到有效的答案。我正在阅读Rails教程的第10章第10.1.2节,但似乎无法使邮件程序预览正常工作。我发现处理错误的所有答案都与教程的不同部分相关,我假设我犯的错误正盯着我的脸。我已经完成并将教程中的代码复制/粘贴到相关文件中,但到目前为止,我还看不出我输入的内容与教程中的内容有什么区别。到目前为止,建议是在函数定义中添加或删除参数user,但这并没有解决问题。触发错误的url是http://localhost:3000/rails/mailers/user_mailer/account_activation.http://localhost:3000/rails/mai

  5. ruby-on-rails - Ruby on Rails - 为文本区域和图片生成列 - 2

    我是Rails的新手,所以请原谅简单的问题。我正在为一家公司创建一个网站。那家公司想在网站上展示它的客户。我想让客户自己管理这个。我正在为“客户”生成一个表格,我想要的三列是:公司名称、公司描述和Logo。对于名称,我使用的是name:string但不确定如何在脚本/生成脚手架终端命令中最好地创建描述列(因为我打算将其设置为文本区域)和图片。我怀疑描述(我想成为一个文本区域)应该仍然是描述:字符串,然后以实际形式进行调整。不确定如何处理图片字段。那么……说来话长:我在脚手架命令中输入什么来生成描述和图片列? 最佳答案 对于“文本”数

  6. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

  7. ruby-on-rails - 如何生成传递一些自定义参数的 `link_to` URL? - 2

    我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些

  8. ruby-on-rails - 如何在 Rails 3 中创建自定义脚手架生成器? - 2

    有这些railscast。http://railscasts.com/episodes/218-making-generators-in-rails-3有了这个,你就会知道如何创建样式表和脚手架生成器。http://railscasts.com/episodes/216-generators-in-rails-3通过这个,您可以了解如何添加一些文件来修改脚手架View。我想把两者结合起来。我想创建一个生成器,它也可以创建脚手架View。有点像RyanBates漂亮的生成器或web_app_themegem(https://github.com/pilu/web-app-theme)。我

  9. 报告回顾丨模型进化狂飙,DetectGPT能否识别最新模型生成结果? - 2

    导读语言模型给我们的生产生活带来了极大便利,但同时不少人也利用他们从事作弊工作。如何规避这些难辨真伪的文字所产生的负面影响也成为一大难题。在3月9日智源Live第33期活动「DetectGPT:判断文本是否为机器生成的工具」中,主讲人Eric为我们讲解了DetectGPT工作背后的思路——一种基于概率曲率检测的用于检测模型生成文本的工具,它可以帮助我们更好地分辨文章的来源和可信度,对保护信息真实、防止欺诈等方面具有重要意义。本次报告主要围绕其功能,实现和效果等展开。(文末点击“阅读原文”,查看活动回放。)Ericmitchell斯坦福大学计算机系四年级博士生,由ChelseaFinn和Chri

  10. ruby-on-rails - 使用 HTTP.get_response 检索 Facebook 访问 token 时出现 Rails EOF 错误 - 2

    我试图在我的网站上实现使用Facebook登录功能,但在尝试从Facebook取回访问token时遇到障碍。这是我的代码:ifparams[:error_reason]=="user_denied"thenflash[:error]="TologinwithFacebook,youmustclick'Allow'toletthesiteaccessyourinformation"redirect_to:loginelsifparams[:code]thentoken_uri=URI.parse("https://graph.facebook.com/oauth/access_token

随机推荐