C# .Net Furion Jwt登录与自动刷新token

前端

axios设置

// 创建一个axios对象
let instance = axios.create({
    baseURL: 'http://localhost:5001/api',
    timeout: 15000,
});
// key 的名称
let _tokenKey = 'access-token';
let _refreshTokenKey = 'x-access-token';

// 请求拦截
instance.interceptors.request.use(
    function (config) {
        // 取出存储的token
        let token = localStorage.getItem(_tokenKey);
        let refreshToken = localStorage.getItem(_refreshTokenKey);
        // 判断是否进行了登录
        if (token != null && refreshToken != null) {
            config.headers['Authorization'] = 'Bearer ' + token;
            config.headers['X-Authorization'] = 'Bearer ' + refreshToken;
        }
        return config;
    },
    function (error) {
        return Promise.reject(error);
    }
);
// 响应拦截
instance.interceptors.response.use(
    function (response) {
        // 服务器返回的headers
        let headers = response.headers;
        let token = headers[_tokenKey];
        let refreshToken = headers[_refreshTokenKey];
        // 判断是否有返回的token(登录和自动刷新都在headers中设置了token)
        if (token != null && refreshToken != null) {
            console.log('存储token');
            //存到localStorage,发送请求时取出
            localStorage.setItem(_tokenKey, token);
            localStorage.setItem(_refreshTokenKey, refreshToken);
        }
        return response;
    },
    function (error) {
        // 对响应错误做点什么
        console.error(error);
        alert('发生了错误');
        return Promise.reject(error);
    }
);

测试

let login = () => {
    instance.post('/user/login', {}).then((r) => {
        console.log('login 返回:', r);
    });
};
let test = () => {
    instance.post('/user/test-jwt',{}).then((r) => {
    	//未登录 返回 401
    	//登录后返回   1----xxxue
        console.log('test 返回:', r);
    });
};

后端

controller

using System.Collections.Generic;
using Furion;
using Furion.DataEncryption;
using Furion.DynamicApiController;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;

namespace Demo.Application.UserController
{
    public class UserAppServices : IDynamicApiController
    {
        // httpContext 访问器
        private readonly IHttpContextAccessor _httpContextAccessor;

        public UserAppServices(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        /// 
        /// Jwt登录
        /// 
        /// 
        [AllowAnonymous] // 允许匿名访问
        public bool Login()
        {
        	// 真实项目中, 需要从数据库查询用户信息
            var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>()
            {
                { "UserId", 1 },
                { "UserName", "xxxue" }
            }, 1); // 过期时间 1分钟,用于测试

            // 下面设置 headers["access-token"] 即可登录. 这里无需重复设置
            //_httpContextAccessor.HttpContext.SigninToSwagger(accessToken);

            // 默认30天,可指定第二个参数设置有效期
            var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken);
            if (_httpContextAccessor.HttpContext != null)
            {
                _httpContextAccessor.HttpContext.Response.Headers["access-token"] = accessToken;
                _httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken;
                // 指定公开的key,这样 axios才能取到值
                _httpContextAccessor.HttpContext.Response.Headers["Access-Control-Expose-Headers"] =
                    "access-token, x-access-token";
            }

            return !string.IsNullOrEmpty(accessToken);
        }

        public string TestJwt()
        {
            // 取出jwt中存储的值
            var id = App.User.FindFirst("UserId");
            var userName = App.User.FindFirst("UserName");
            return id + " --- " + userName;
        }
    }
}

JwtHandler

using System;
using Furion.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;
using Furion.DataEncryption;

namespace Demo.Web.Core
{
    public class JwtHandler : AppAuthorizeHandler
    {
        public override async Task HandleAsync(AuthorizationHandlerContext context)
        {
            Console.WriteLine("进入jwt验证");
            
            var currentHttpContext = context.GetCurrentHttpContext();
            // 检查并自动刷新 token, (第三个参数,新token有效期设置为1分钟,便于测试)
            if (JWTEncryption.AutoRefreshToken(context, currentHttpContext, 1))
            {
                await AuthorizeHandleAsync(context);
            }
            else
            {
                context.Fail(); // 授权失败
            }
        }

        public override Task<bool> PipelineAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext)
        {
            // 这里写您的授权判断逻辑,授权通过返回 true,否则返回 false
            return Task.FromResult(true);
        }
    }
}


startup

using Furion;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using Serilog;

namespace Demo.Web.Core
{
    public class Startup : AppStartup
    {
        public void ConfigureServices(IServiceCollection services)
        {
        	// 注册jwt处理方法,开启全局验证,
        	//除了标注 [AllowAnonymous] 特性,其他的方法都需要登录才可以访问
            services.AddJwt<JwtHandler>(enableGlobalAuthorize:true);
            
			//.. 省略
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
			//.. 省略
			// 开启认证
			app.UseAuthentication();
			app.UseAuthorization();
			//.. 省略
        }
    }
}

你可能感兴趣的:(C#,c#,jwt,刷新token,Furion,.net)