Skip to content

Commit 46882c5

Browse files
committed
重写http.js、token过期自动刷新机制(需要更新前端http.js,后台Sys_UserController.cs,ApiAuthorizeFilter.cs,HttpRequestMiddleware.cs)
1 parent dcfdbd9 commit 46882c5

File tree

9 files changed

+671
-482
lines changed

9 files changed

+671
-482
lines changed

Vol.Vue/src/api/http.js

Lines changed: 216 additions & 230 deletions
Large diffs are not rendered by default.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
@media screen and (max-width: 600px) {
2+
.g-left{
3+
display: none;
4+
}
5+
.g-right{
6+
margin: 0 !important;
7+
span,p{
8+
font-size: 0.8rem !important;
9+
line-height: 2 !important;
10+
}
11+
li{
12+
padding-left: 0 !important;
13+
}
14+
}
15+
.content{
16+
padding: 0 !important;
17+
padding-right: 3px !important;
18+
}
19+
.links {
20+
display: none !important;
21+
}
22+
.doc-menu{
23+
24+
font-size: 1.5rem;
25+
padding: 0.2rem 0.5rem;
26+
border-bottom: 1px solid #eee;
27+
display: block !important;
28+
29+
}
30+
.g-p{
31+
text-align: center;
32+
padding: 0.5rem;
33+
a{
34+
font-size: 1.3rem !important;
35+
margin: 0 !important;
36+
padding: 0.4rem;
37+
}
38+
}
39+
.coder-container{
40+
.left{
41+
display: none !important;
42+
}
43+
.right{
44+
margin: 0 !important;
45+
}
46+
}
47+
.i-container{
48+
padding: 1rem;
49+
.list{
50+
margin: 0 !important;
51+
}
52+
.nav{
53+
display: none !important;
54+
}
55+
}
56+
57+
}

Vue.Net/VOL.Core/Filters/ApiAuthorizeFilter.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public void OnAuthorization(AuthorizationFilterContext context)
2929
{
3030
// is Microsoft.AspNetCore.Authentication.AllowAnonymousAttribute
3131
//if (context.Filters.Any(item => item is IAllowAnonymousFilter))
32-
if (context.ActionDescriptor.EndpointMetadata.Any(item => item is AllowAnonymousAttribute))
32+
if (context.ActionDescriptor.EndpointMetadata.Any(item => item is IAllowAnonymous))
3333
{
3434
//如果使用了固定Token不过期,直接对token的合法性及token是否存在进行验证
3535
if (context.Filters
@@ -66,11 +66,10 @@ public void OnAuthorization(AuthorizationFilterContext context)
6666

6767
DateTime expDate = context.HttpContext.User.Claims.Where(x => x.Type == JwtRegisteredClaimNames.Exp)
6868
.Select(x => x.Value).FirstOrDefault().GetTimeSpmpToDate();
69-
//如果过期时间小于设置定分钟数的1/3时,返回状态需要刷新token
70-
if (expDate < DateTime.Now || (expDate - DateTime.Now).TotalMinutes < AppSetting.ExpMinutes / 3)
69+
//动态标识刷新token(2021.05.01)
70+
if ((expDate - DateTime.Now).TotalMinutes < AppSetting.ExpMinutes/3)
7171
{
72-
context.FilterResult(HttpStatusCode.Accepted, "Token即将过期,请更换token");//202
73-
return;
72+
context.HttpContext.Response.Headers.Add("vol_exp", "1");
7473
}
7574
}
7675
}

Vue.Net/VOL.Core/Middleware/HttpRequestMiddleware.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ public static Func<RequestDelegate, RequestDelegate> Context
1414
{
1515
return next => async context =>
1616
{
17-
17+
//动态标识刷新token(2021.05.01)
18+
context.Response.Headers.Add("Access-Control-Expose-Headers", "vol_exp");
1819
var stream = context.Request.Body;
1920
if (stream == Stream.Null || stream.CanSeek)
2021
{

Vue.Net/VOL.WebApi/Controllers/System/Partial/Sys_UserController.cs

Lines changed: 85 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,24 @@
22
using Microsoft.AspNetCore.Authorization;
33
using Microsoft.AspNetCore.Mvc;
44
using Microsoft.Extensions.Caching.Memory;
5+
using Microsoft.Extensions.DependencyInjection;
56
using System;
7+
using System.Collections.Concurrent;
8+
using System.Linq;
69
using System.Linq.Expressions;
710
using System.Threading.Tasks;
11+
using VOL.Core.CacheManager;
812
using VOL.Core.Configuration;
913
using VOL.Core.Controllers.Basic;
1014
using VOL.Core.DBManager;
1115
using VOL.Core.EFDbContext;
16+
using VOL.Core.Enums;
1217
using VOL.Core.Extensions;
1318
using VOL.Core.Filters;
1419
using VOL.Core.Infrastructure;
1520
using VOL.Core.ManageUser;
1621
using VOL.Core.ObjectActionValidator;
22+
using VOL.Core.Services;
1723
using VOL.Core.Utilities;
1824
using VOL.Entity.AttributeManager;
1925
using VOL.Entity.DomainModels;
@@ -26,19 +32,93 @@ namespace VOL.System.Controllers
2632
[Route("api/User")]
2733
public partial class Sys_UserController
2834
{
35+
private ISys_UserRepository _userRepository;
36+
private ICacheService _cache;
37+
[ActivatorUtilitiesConstructor]
38+
public Sys_UserController(
39+
ISys_UserService userService,
40+
ISys_UserRepository userRepository,
41+
ICacheService cahce
42+
)
43+
: base(userService)
44+
{
45+
_userRepository = userRepository;
46+
_cache = cahce;
47+
}
48+
2949
[HttpPost, HttpGet, Route("login"), AllowAnonymous]
3050
[ObjectModelValidatorFilter(ValidatorModel.Login)]
31-
public async Task<IActionResult> Login([FromBody]LoginInfo loginInfo)
51+
public async Task<IActionResult> Login([FromBody] LoginInfo loginInfo)
3252
{
3353
return Json(await Service.Login(loginInfo));
3454
}
3555

36-
[HttpPost, Route("replaceToken"), AllowAnonymous]
37-
public async Task<IActionResult> ReplaceToken()
56+
private readonly ConcurrentDictionary<int, object> _lockCurrent = new ConcurrentDictionary<int, object>();
57+
[HttpPost, Route("replaceToken")]
58+
public IActionResult ReplaceToken()
3859
{
39-
return Json(await Service.ReplaceToken());
60+
WebResponseContent responseContent = new WebResponseContent();
61+
string error = "";
62+
string key = $"rp:Token:{UserContext.Current.UserId}";
63+
UserInfo userInfo = null;
64+
try
65+
{
66+
//如果5秒内替换过token,直接使用最新的token(防止一个页面多个并发请求同时替换token导致token错位)
67+
if (_cache.Exists(key))
68+
{
69+
return Json(responseContent.OK(null, _cache.Get(key)));
70+
}
71+
var _obj = _lockCurrent.GetOrAdd(UserContext.Current.UserId, new object() { });
72+
lock (_obj)
73+
{
74+
if (_cache.Exists(key))
75+
{
76+
return Json(responseContent.OK(null, _cache.Get(key)));
77+
}
78+
string requestToken = HttpContext.Request.Headers[AppSetting.TokenHeaderName];
79+
requestToken = requestToken?.Replace("Bearer ", "");
80+
81+
if (JwtHelper.IsExp(requestToken)) return Json(responseContent.Error("Token已过期!"));
82+
83+
int userId = UserContext.Current.UserId;
84+
85+
userInfo = _userRepository.FindAsIQueryable(x => x.User_Id == userId).Select(
86+
s => new UserInfo()
87+
{
88+
User_Id = userId,
89+
UserName = s.UserName,
90+
UserTrueName = s.UserTrueName,
91+
Role_Id = s.Role_Id,
92+
RoleName = s.RoleName
93+
}).FirstOrDefault();
94+
95+
if (userInfo == null) return Json(responseContent.Error("未查到用户信息!"));
96+
97+
string token = JwtHelper.IssueJwt(userInfo);
98+
//移除当前缓存
99+
_cache.Remove(userId.GetUserIdKey());
100+
//只更新的token字段
101+
_userRepository.Update(new Sys_User() { User_Id = userId, Token = token }, x => x.Token, true);
102+
//添加一个5秒缓存
103+
_cache.Add(key, token, 5);
104+
responseContent.OK(null, token);
105+
}
106+
}
107+
catch (Exception ex)
108+
{
109+
error = ex.Message + ex.StackTrace;
110+
responseContent.Error("token替换异常");
111+
}
112+
finally
113+
{
114+
_lockCurrent.TryRemove(UserContext.Current.UserId, out object val);
115+
string _message = $"用户{userInfo?.User_Id}_{userInfo?.UserTrueName},({(responseContent.Status ? "token替换成功": "token替换失败")})";
116+
Logger.Info(LoggerType.ReplaceToeken, _message, null, error);
117+
}
118+
return Json(responseContent);
40119
}
41120

121+
42122
[HttpPost, Route("modifyPwd")]
43123
[ApiActionPermission]
44124
//通过ObjectGeneralValidatorFilter校验参数,不再需要if esle判断OldPwd与NewPwd参数
@@ -76,7 +156,7 @@ public IActionResult ModifyUserPwd(string password, string userName)
76156
repository.Update(user, x => new { x.UserPwd }, true);
77157
//如果用户在线,强制下线
78158
UserContext.Current.LogOut(user.User_Id);
79-
return Json(webResponse.OK("密码修改成功"));
159+
return Json(webResponse.OK("密码修改成功"));
80160
}
81161

82162
/// <summary>

0 commit comments

Comments
 (0)