zoukankan      html  css  js  c++  java
  • .NET Core 3.X 使用 JWT 案例

    在前后端分离的架构中,前端需要通过 API 接口的方式获取数据,但 API 是无状态的,没有办法知道每次请求的身份,也就没有办法做权限的控制。

    如果不做控制,API 就对任何人敞开了大门,只要拿到了接口地址就可以进行调用,这是非常危险的。

    本文主要介绍下在 dotNET Core Web API 中使用 Jwt 来实现接口的认证。

    Jwt 简介

    Jwt 的全称是 JSON Web Token,是目前比较流行的接口认证解决方案。有了 Jwt 后,从客户端请求接口的流程如下图:

    • 客户端发送用户名密码信息到认证服务器获取 token;
    • 客户端请求 API 获取数据时带上 token;
    • 服务器端验证 token,合法则返回正确的数据。

    有一个网站叫:https://jwt.io/ ,我们在这个站点上对 Jwt 产生的 token 做验证:

    从上图可以看出 Jwt 生产的 token 由三个部分组成:

    • Header(红色):头
    • Playload(紫色):负载
    • Verify Sigantuer(蓝色):签名

    这三个部分由英文的点进行分隔开

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoib2VjMjAwMyIsInNpdGUiOiJodHRwOi8vZndoeXkuY29tIiwiaWF0IjoxNTE2MjM5MDIyfQ.DYgo4eEUwlYJqQoLvAuFPxFRVcCow77Zyl2byaK6Uxk

    头信息是一个 Json 格式的数据

    {
    "alg": "HS256",
    "typ": "JWT"
    }
    • alg:表示加密的算法
    • typ:表示 token 的类型

    Playload

    Playload 是 token 的主体内容部分,我们可以用来传递一些信息给客户端,比如过期时间就是通过 Playload 来进行传递的。 但因为默认情况下 Playload 的数据是明文的,所以敏感信息不要放在这里。

    Verify Sigantuer

    Verify Sigantuer 是对前面两个部分的签名,防止数据篡改。

    使用 Jwt

    下面一步步介绍在 dotNET Core Web API 项目中使用 Jwt:

    1、添加 Jwt 的包引用

    在 Web API 项目中添加对 Microsoft.AspNetCore.Authentication.JwtBearer 包的引用

    2、修改 Starup

    Starup 类中的ConfigureServices 方法添加如下代码:

    //解决跨域问题
                services.AddCors(options =>
                {
                    options.AddPolicy("CorsPolicy",
                        builder => builder.AllowAnyOrigin()
                            .AllowAnyMethod()
                            .AllowAnyHeader());
                });
    
    // jwt 认证
                JwtSettings jwtSettings = new JwtSettings();
                services.Configure<JwtSettings>(Configuration.GetSection("JwtSettings"));
                Configuration.GetSection("JwtSettings").Bind(jwtSettings);
    
                services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                    .AddJwtBearer(o =>
                    {
                        o.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
                        {
                            ValidateIssuerSigningKey = true,
                            ValidIssuer = jwtSettings.Issuer,
                            ValidAudience = jwtSettings.Audience,
                            //用于签名验证
                            IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtSettings.SecretKey)),
                                        ValidateIssuer = false,
                                        ValidateAudience = false
                                    };
                    });

    3、添加 JwtSettings 对象

       public class JwtSettings
        {
            public string Issuer { get; set; }
    
            public string Audience { get; set; }
    
    
            public string SecretKey { get; set; }
        }

    4、appsettings.json 文件中添加 JwtSettings 配置:

    SecretKey 字段必须是16的倍数。
     "JwtSettings": {
        "Audience": "123456",
        "Issuer": "123456", 
    "SecretKey": "
    ihGpquvKl4POannM"
    }

    5、Startup 类中的 Configure 方法添加如下代码:

      //解决跨域问题
      app.UseCors("CorsPolicy");
    
      IdentityModelEventSource.ShowPII = true;

       app.UseRouting();

    
    

       //顺序不能颠倒

       app.UseAuthentication();
       app.UseAuthorization();

    
    

    6、添加AuthorizeController 控制器

    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 coreTest.Common.Model;
    using coreTest.Model;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Options;
    using Microsoft.IdentityModel.Tokens;
    
    namespace coreTest.Controllers
    {
        [Route("api/[controller]")]
        [ApiController]
        public class AuthorizeController : ControllerBase
        {
            
            private readonly JwtSettings _jwtSettings;
    
            public AuthorizeController(IOptions<JwtSettings> options) 
            {
         
                _jwtSettings = options.Value;
            }
    
            [HttpPost]
            [Route("Token")]
            public Result<string> Token(User user)
            {
                Result<string> result = new Result<string>();
    
                if (user == null) {
                    result.Data = string.Empty;
                    return result;
                }
                if (user.UserName == "admin" && user.Pwd == "123456")
                {
                    var claims = new Claim[]
                      {
                         new Claim(ClaimTypes.Name,user.UserName)
                      };
                    
                    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.SecretKey));
                    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
    
                    var token = new JwtSecurityToken(_jwtSettings.Issuer,
                        _jwtSettings.Audience,
                        claims,
                        DateTime.Now,
                        DateTime.Now.AddMinutes(10),
                        creds);
    
                    string res = new JwtSecurityTokenHandler().WriteToken(token);
    
                    result.Data = res;
                    return result;
    
                }
                return result;
    
            }
    
        }
    }
    Result 类:
    public class Result<T>
        {
            public Result()
            {
                ReturnCode = ReturnCode.Fail;
                ReturnMsg = "未知错误";
            }
            public ReturnCode ReturnCode { get; set; }
            public string ReturnMsg { get; set; }
    
            public T Data { get; set; }
        }

    7、在需要进行认证的控制器或接口方法上添加 [Authorize] 标记。 添加 SysUserController 控制器 ,如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using coreTest.IService;
    using coreTest.Model;
    using Dapper.Extension.AspNetCore;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Logging;
    
    namespace coreTest.Controllers
    {
        [Authorize]
        [Route("api/[controller]")]
        [ApiController]
        public class SysUserController : ControllerBase
        {
            private readonly ILogger<SysUserController> logger;
            private readonly IDapper dapper;
            private readonly ISysUserService sysUserService;
    
            public SysUserController(ILogger<SysUserController> _logger, IDapper _dapper, ISysUserService _sysUserService)
            {
    
                logger = _logger;
                dapper = _dapper;
                sysUserService = _sysUserService;
            }
    
            [HttpGet]
            [Route("Index")]
            public JsonResult Index(int pageIndex = 1, int pageSize = 10)
            {
                var result = sysUserService.GetList(pageIndex, pageSize);
                return new JsonResult(result);
            }
    
        }
    }

    8、使用 Postman 测试

     1)、调用接口 http://localhost:5000/api/Authorize/token 获取 token。

     

     2)、在请求接口时使用 Authorization 的方式使用 token,token 的类型为 Bearer Token ,可以看到带上 token 后,数据正常返回。

    9、前端ajax调用案例

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="js/jquery-3.5.1.js"></script>
    </head>
    <body>
    
            <input  type="button" value="登录" onclick="submit()" />
            <input  type="button" value="获取数据" onclick="getData()" />
    
        <script>
            let Authorization = '';
            function submit(){
                console.log(111);
                let url = "http://localhost:4213/api/Authorize/Token";
                let p = {
                    "userName": "admin",
                    "pwd": "123456"
                };
    
                $.ajax({
                    type: 'post',
                    url: url,
                    dataType: 'json',
                    cache: false,
                    headers : {
                        'Content-Type' : 'application/json;charset=utf-8',
                    },
                    data: JSON.stringify(p),
                    success: function (data) {
                        console.log('success');
                        console.log(data);
                        console.log(data.data);
                        Authorization = 'Bearer '+data.data;
                    },
                    error: function(er){
                        console.log('error');
                        console.log(er);
                        console.log(er.responseText);
    
                    }
    
                });
    
            }
    
            function getData(){
                let getUrl = "http://localhost:4213/api/SysUser/Index?pageIndex=1&pageSize=10";
                $.ajax({
                    type: 'get',
                    url: getUrl,
                    dataType: 'json',
                    cache: false,
                    headers : {
                        'Content-Type' : 'application/json;charset=utf-8',
                        'Authorization':Authorization
                    },
                    // data: JSON.stringify(paramData),
                    success: function (data) {
                        console.log(data);
                    },
                    error: function(er){
    
                    }
    
                });
            }
        </script>
    </body>
    </html>
  • 相关阅读:
    famous summary stack trace from Oracle Version 8.1.7.4.0 Bug Note
    Mysql:命令选项、配置选项、(全局、会话)系统变量、状态变量:状态变量
    Mysql:命令选项、配置选项、(全局、会话)系统变量、状态变量:(仅会话)系统变量
    Mysql:命令选项、配置选项、(全局、会话)系统变量、状态变量:命令选项
    Mysql:命令选项、配置选项、(全局、会话)系统变量、状态变量:系统变量
    Mysql:命令选项、配置选项、(全局、会话)系统变量、状态变量:(动态)系统变量
    正式入住CSDN了
    关于ansi控制码
    源码网站
    Imail2006 联系人???问题解决
  • 原文地址:https://www.cnblogs.com/zoro-zero/p/14235419.html
Copyright © 2011-2022 走看看