更换jwtToken 为Bearer
This commit is contained in:
parent
c6a523834c
commit
42dc24b6b8
@ -14,7 +14,7 @@ namespace Infrastructure
|
|||||||
|
|
||||||
static ConfigUtils()
|
static ConfigUtils()
|
||||||
{
|
{
|
||||||
Config = App.ServiceProvider.GetRequiredService<IConfiguration>();
|
Configuration = App.ServiceProvider.GetRequiredService<IConfiguration>();
|
||||||
|
|
||||||
if (Instance == null)
|
if (Instance == null)
|
||||||
Instance = new ConfigUtils();
|
Instance = new ConfigUtils();
|
||||||
@ -22,35 +22,22 @@ namespace Infrastructure
|
|||||||
|
|
||||||
public static ConfigUtils Instance { get; private set; }
|
public static ConfigUtils Instance { get; private set; }
|
||||||
#endregion
|
#endregion
|
||||||
|
private static IConfiguration Configuration { get; set; }
|
||||||
private static IConfiguration Config { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 泛型读取配置文件
|
|
||||||
/// 目前还不能绑定到实体类
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="defaultValue">获取不到配置文件设定默认值</param>
|
|
||||||
/// <param name="key">要获取的配置文件节点名称</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
//public T GetConfig<T>(string key, T defaultValue = default)
|
|
||||||
//{
|
|
||||||
// //GetValue扩展包需要安装Microsoft.Extensions.Configuration
|
|
||||||
// var setting = Config.GetValue(key, defaultValue);
|
|
||||||
|
|
||||||
// Console.WriteLine($"获取配置文件值key={key},value={setting}");
|
|
||||||
// return setting;
|
|
||||||
//}
|
|
||||||
|
|
||||||
public T GetAppConfig<T>(string key, T defaultValue = default(T))
|
public T GetAppConfig<T>(string key, T defaultValue = default(T))
|
||||||
{
|
{
|
||||||
T setting = (T)Convert.ChangeType(Config[key], typeof(T));
|
T setting = (T)Convert.ChangeType(Configuration[key], typeof(T));
|
||||||
var value = setting;
|
var value = setting;
|
||||||
if (setting == null)
|
if (setting == null)
|
||||||
value = defaultValue;
|
value = defaultValue;
|
||||||
//Console.WriteLine($"获取配置文件值key={key},value={value}");
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
public T Bind<T>(string key, T t)
|
||||||
|
{
|
||||||
|
Configuration.Bind(key, t);
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取配置文件
|
/// 获取配置文件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -58,7 +45,7 @@ namespace Infrastructure
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public string GetConfig(string key)
|
public string GetConfig(string key)
|
||||||
{
|
{
|
||||||
return Config[key];
|
return Configuration[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -66,10 +53,9 @@ namespace Infrastructure
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key"></param>
|
/// <param name="key"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public string GetConnectionStrings(string key)
|
public string GetConnectionString(string key)
|
||||||
{
|
{
|
||||||
return Config.GetConnectionString(key);
|
return Configuration.GetConnectionString(key);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,4 +50,27 @@ namespace Infrastructure
|
|||||||
public string KEY { get; set; }
|
public string KEY { get; set; }
|
||||||
public string SECRET { get; set; }
|
public string SECRET { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Jwt
|
||||||
|
/// </summary>
|
||||||
|
public class JwtSettings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// token是谁颁发的
|
||||||
|
/// </summary>
|
||||||
|
public string Issuer { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// token可以给那些客户端使用
|
||||||
|
/// </summary>
|
||||||
|
public string Audience { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 加密的key(SecretKey必须大于16个,是大于,不是大于等于)
|
||||||
|
/// </summary>
|
||||||
|
public string SecretKey { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// token时间(分)
|
||||||
|
/// </summary>
|
||||||
|
public int Expire { get; set; } = 1440;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -79,7 +79,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
|||||||
#endregion
|
#endregion
|
||||||
LoginUser loginUser = new LoginUser(user.UserId, user.UserName, roles, permissions);
|
LoginUser loginUser = new LoginUser(user.UserId, user.UserName, roles, permissions);
|
||||||
|
|
||||||
return SUCCESS(JwtUtil.GenerateJwtToken(HttpContext.WriteCookies(loginUser)));
|
return SUCCESS(JwtUtil.GenerateJwtToken(HttpContext.AddClaims(loginUser)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -90,11 +90,11 @@ namespace ZR.Admin.WebApi.Controllers.System
|
|||||||
[HttpPost("logout")]
|
[HttpPost("logout")]
|
||||||
public IActionResult LogOut()
|
public IActionResult LogOut()
|
||||||
{
|
{
|
||||||
Task.Run(async () =>
|
//Task.Run(async () =>
|
||||||
{
|
//{
|
||||||
//注销登录的用户,相当于ASP.NET中的FormsAuthentication.SignOut
|
// //注销登录的用户,相当于ASP.NET中的FormsAuthentication.SignOut
|
||||||
await HttpContext.SignOutAsync();
|
// await HttpContext.SignOutAsync();
|
||||||
}).Wait();
|
//}).Wait();
|
||||||
|
|
||||||
return SUCCESS(1);
|
return SUCCESS(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using Infrastructure;
|
using Infrastructure;
|
||||||
using Microsoft.AspNetCore.Authentication;
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
@ -67,7 +68,7 @@ namespace ZR.Admin.WebApi.Extensions
|
|||||||
{
|
{
|
||||||
var uid = context.User.FindFirstValue(ClaimTypes.PrimarySid);
|
var uid = context.User.FindFirstValue(ClaimTypes.PrimarySid);
|
||||||
|
|
||||||
return !string.IsNullOrEmpty(uid) ? long.Parse(uid) : 0 ;
|
return !string.IsNullOrEmpty(uid) ? long.Parse(uid) : 0;
|
||||||
}
|
}
|
||||||
public static string GetName(this HttpContext context)
|
public static string GetName(this HttpContext context)
|
||||||
{
|
{
|
||||||
@ -75,6 +76,16 @@ namespace ZR.Admin.WebApi.Extensions
|
|||||||
|
|
||||||
return uid;
|
return uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ClaimsIdentity
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<ClaimsIdentity> GetClaims(this HttpContext context)
|
||||||
|
{
|
||||||
|
return context.User?.Identities;
|
||||||
|
}
|
||||||
//public static int GetRole(this HttpContext context)
|
//public static int GetRole(this HttpContext context)
|
||||||
//{
|
//{
|
||||||
// var roleid = context.User.FindFirstValue(ClaimTypes.Role) ?? "0";
|
// var roleid = context.User.FindFirstValue(ClaimTypes.Role) ?? "0";
|
||||||
@ -84,9 +95,7 @@ namespace ZR.Admin.WebApi.Extensions
|
|||||||
|
|
||||||
public static string GetUserAgent(this HttpContext context)
|
public static string GetUserAgent(this HttpContext context)
|
||||||
{
|
{
|
||||||
var str = context.Request.Headers["User-Agent"];
|
return context.Request.Headers["User-Agent"];
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -96,9 +105,7 @@ namespace ZR.Admin.WebApi.Extensions
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static string GetToken(this HttpContext context)
|
public static string GetToken(this HttpContext context)
|
||||||
{
|
{
|
||||||
var str = context.Request.Headers["Token"];
|
return context.Request.Headers["Authorization"];
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ClientInfo GetClientInfo(this HttpContext context)
|
public static ClientInfo GetClientInfo(this HttpContext context)
|
||||||
@ -116,12 +123,12 @@ namespace ZR.Admin.WebApi.Extensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 登录cookie写入
|
///组装Claims
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context"></param>
|
/// <param name="context"></param>
|
||||||
/// <param name="user"></param>
|
/// <param name="user"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static List<Claim> WriteCookies(this HttpContext context, LoginUser user)
|
public static List<Claim> AddClaims(this HttpContext context, LoginUser user)
|
||||||
{
|
{
|
||||||
//1、创建Cookie保存用户信息,使用claim
|
//1、创建Cookie保存用户信息,使用claim
|
||||||
var claims = new List<Claim>()
|
var claims = new List<Claim>()
|
||||||
@ -138,13 +145,21 @@ namespace ZR.Admin.WebApi.Extensions
|
|||||||
{
|
{
|
||||||
claims.Add(new Claim("perm", string.Join(",", user.Permissions)));
|
claims.Add(new Claim("perm", string.Join(",", user.Permissions)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//写入Cookie
|
||||||
|
//WhiteCookie(context, claims);
|
||||||
|
return claims;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WhiteCookie(HttpContext context, List<Claim> claims)
|
||||||
|
{
|
||||||
//2.创建声明主题 指定认证方式 这里使用cookie
|
//2.创建声明主题 指定认证方式 这里使用cookie
|
||||||
var claimsIdentity = new ClaimsIdentity(claims, "Login");
|
var claimsIdentity = new ClaimsIdentity(claims, "Login");
|
||||||
|
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
await context.SignInAsync(
|
await context.SignInAsync(
|
||||||
CookieAuthenticationDefaults.AuthenticationScheme,//这里要注意的是HttpContext.SignInAsync(AuthenticationType,…) 所设置的Scheme一定要与前面的配置一样,这样对应的登录授权才会生效。
|
JwtBearerDefaults.AuthenticationScheme,//这里要注意的是HttpContext.SignInAsync(AuthenticationType,…) 所设置的Scheme一定要与前面的配置一样,这样对应的登录授权才会生效。
|
||||||
new ClaimsPrincipal(claimsIdentity),
|
new ClaimsPrincipal(claimsIdentity),
|
||||||
new AuthenticationProperties()
|
new AuthenticationProperties()
|
||||||
{
|
{
|
||||||
@ -153,7 +168,6 @@ namespace ZR.Admin.WebApi.Extensions
|
|||||||
ExpiresUtc = DateTimeOffset.Now.AddDays(1),//有效时间
|
ExpiresUtc = DateTimeOffset.Now.AddDays(1),//有效时间
|
||||||
});
|
});
|
||||||
}).Wait();
|
}).Wait();
|
||||||
return claims;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@ using NLog;
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using ZR.Admin.WebApi.Extensions;
|
using ZR.Admin.WebApi.Extensions;
|
||||||
|
using ZR.Admin.WebApi.Framework;
|
||||||
using ZR.Model.System;
|
using ZR.Model.System;
|
||||||
|
|
||||||
namespace ZR.Admin.WebApi.Filters
|
namespace ZR.Admin.WebApi.Filters
|
||||||
@ -44,12 +45,10 @@ namespace ZR.Admin.WebApi.Filters
|
|||||||
string ip = HttpContextExtension.GetClientUserIp(context.HttpContext);
|
string ip = HttpContextExtension.GetClientUserIp(context.HttpContext);
|
||||||
string url = context.HttpContext.Request.Path;
|
string url = context.HttpContext.Request.Path;
|
||||||
var isAuthed = context.HttpContext.User.Identity.IsAuthenticated;
|
var isAuthed = context.HttpContext.User.Identity.IsAuthenticated;
|
||||||
// 检查登陆 - 在SignIn中判断用户合法性,将登陆信息保存在Cookie中,在SignOut中移除登陆信息
|
|
||||||
var userName = context.HttpContext.User.Identity.Name;
|
var userName = context.HttpContext.User.Identity.Name;
|
||||||
|
|
||||||
//使用jwt token校验2020-11-21
|
//使用jwt token校验2020-11-21
|
||||||
//string token = context.HttpContext.Request.Headers["Token"];
|
LoginUser info = JwtUtil.GetLoginUser(context.HttpContext);
|
||||||
LoginUser info = Framework.JwtUtil.GetLoginUser(context.HttpContext);
|
|
||||||
|
|
||||||
if (info != null && info.UserId > 0)
|
if (info != null && info.UserId > 0)
|
||||||
{
|
{
|
||||||
@ -58,7 +57,7 @@ namespace ZR.Admin.WebApi.Filters
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
string msg = $"请求访问:{url}授权认证失败,无法访问系统资源";
|
string msg = $"请求访问:{url}授权认证失败,无法访问系统资源";
|
||||||
logger.Info(msg);
|
logger.Info($"用户{userName}{msg}");
|
||||||
|
|
||||||
context.Result = new JsonResult(new ApiResult((int)ResultCode.DENY, msg));
|
context.Result = new JsonResult(new ApiResult((int)ResultCode.DENY, msg));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,8 +18,6 @@ namespace ZR.Admin.WebApi.Framework
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class JwtUtil
|
public class JwtUtil
|
||||||
{
|
{
|
||||||
public static readonly string KEY = "asdfghjklzxcvbnm";
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取用户身份信息
|
/// 获取用户身份信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -28,6 +26,7 @@ namespace ZR.Admin.WebApi.Framework
|
|||||||
public static LoginUser GetLoginUser(HttpContext httpContext)
|
public static LoginUser GetLoginUser(HttpContext httpContext)
|
||||||
{
|
{
|
||||||
string token = HttpContextExtension.GetToken(httpContext);
|
string token = HttpContextExtension.GetToken(httpContext);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(token))
|
if (!string.IsNullOrEmpty(token))
|
||||||
{
|
{
|
||||||
return ValidateJwtToken(ParseToken(token));
|
return ValidateJwtToken(ParseToken(token));
|
||||||
@ -42,21 +41,52 @@ namespace ZR.Admin.WebApi.Framework
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static string GenerateJwtToken(List<Claim> claims)
|
public static string GenerateJwtToken(List<Claim> claims)
|
||||||
{
|
{
|
||||||
|
JwtSettings jwtSettings = new();
|
||||||
|
ConfigUtils.Instance.Bind("JwtSettings", jwtSettings);
|
||||||
|
|
||||||
var tokenHandler = new JwtSecurityTokenHandler();
|
var tokenHandler = new JwtSecurityTokenHandler();
|
||||||
var key = Encoding.ASCII.GetBytes(KEY);
|
var key = Encoding.ASCII.GetBytes(jwtSettings.SecretKey);
|
||||||
var expires = ConfigUtils.Instance.GetAppConfig("sysConfig:tokenExpire", 10);
|
claims.Add(new Claim("Audience", jwtSettings.Audience));
|
||||||
|
claims.Add(new Claim("Issuer", jwtSettings.Issuer));
|
||||||
|
|
||||||
var tokenDescriptor = new SecurityTokenDescriptor
|
var tokenDescriptor = new SecurityTokenDescriptor
|
||||||
{
|
{
|
||||||
Subject = new ClaimsIdentity(claims),
|
Subject = new ClaimsIdentity(claims),
|
||||||
//Issuer = "",
|
Issuer = jwtSettings.Issuer,
|
||||||
//Audience = "",
|
Audience = jwtSettings.Audience,
|
||||||
Expires = DateTime.Now.AddMinutes(expires),
|
IssuedAt = DateTime.Now,//token生成时间
|
||||||
|
Expires = DateTime.Now.AddMinutes(jwtSettings.Expire),
|
||||||
|
TokenType = "Bearer",
|
||||||
|
//对称秘钥,签名证书
|
||||||
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
|
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
|
||||||
};
|
};
|
||||||
var token = tokenHandler.CreateToken(tokenDescriptor);
|
var token = tokenHandler.CreateToken(tokenDescriptor);
|
||||||
return tokenHandler.WriteToken(token);
|
return tokenHandler.WriteToken(token);
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 验证Token
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static TokenValidationParameters ValidParameters()
|
||||||
|
{
|
||||||
|
JwtSettings jwtSettings = new();
|
||||||
|
ConfigUtils.Instance.Bind("JwtSettings", jwtSettings);
|
||||||
|
|
||||||
|
var key = Encoding.ASCII.GetBytes(jwtSettings.SecretKey);
|
||||||
|
|
||||||
|
var tokenDescriptor = new TokenValidationParameters
|
||||||
|
{
|
||||||
|
ValidateIssuerSigningKey = true,
|
||||||
|
ValidateIssuer = true,
|
||||||
|
ValidateAudience = true,
|
||||||
|
ValidIssuer = jwtSettings.Issuer,
|
||||||
|
ValidAudience = jwtSettings.Audience,
|
||||||
|
IssuerSigningKey = new SymmetricSecurityKey(key),
|
||||||
|
ValidateLifetime = true,//是否验证Token有效期,使用当前时间与Token的Claims中的NotBefore和Expires对比
|
||||||
|
RequireExpirationTime = true,//过期时间
|
||||||
|
};
|
||||||
|
return tokenDescriptor;
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从令牌中获取数据声明
|
/// 从令牌中获取数据声明
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -65,21 +95,13 @@ namespace ZR.Admin.WebApi.Framework
|
|||||||
public static IEnumerable<Claim> ParseToken(string token)
|
public static IEnumerable<Claim> ParseToken(string token)
|
||||||
{
|
{
|
||||||
var tokenHandler = new JwtSecurityTokenHandler();
|
var tokenHandler = new JwtSecurityTokenHandler();
|
||||||
var key = Encoding.ASCII.GetBytes(KEY);
|
var validateParameter = ValidParameters();
|
||||||
|
token = token.Replace("Bearer ", "");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
tokenHandler.ValidateToken(token, new TokenValidationParameters
|
tokenHandler.ValidateToken(token, validateParameter, out SecurityToken validatedToken);
|
||||||
{
|
|
||||||
ValidateIssuerSigningKey = true,
|
|
||||||
IssuerSigningKey = new SymmetricSecurityKey(key),
|
|
||||||
ValidateIssuer = false,
|
|
||||||
ValidateAudience = false,
|
|
||||||
// set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later)
|
|
||||||
ClockSkew = TimeSpan.Zero
|
|
||||||
}, out SecurityToken validatedToken);
|
|
||||||
|
|
||||||
//{{"alg":"HS256","typ":"JWT"}.{"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/sid":"2","unique_name":"ry","nameid":"2","given_name":"若依","nbf":1606654010,"exp":1606740410,"iat":1606654010}}
|
var jwtToken = tokenHandler.ReadJwtToken(token);
|
||||||
var jwtToken = (JwtSecurityToken)validatedToken;
|
|
||||||
return jwtToken.Claims;
|
return jwtToken.Claims;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ using Hei.Captcha;
|
|||||||
using Infrastructure;
|
using Infrastructure;
|
||||||
using Infrastructure.Extensions;
|
using Infrastructure.Extensions;
|
||||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.DataProtection;
|
using Microsoft.AspNetCore.DataProtection;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
@ -55,11 +56,23 @@ namespace ZR.Admin.WebApi
|
|||||||
services.AddSession();
|
services.AddSession();
|
||||||
services.AddHttpContextAccessor();
|
services.AddHttpContextAccessor();
|
||||||
|
|
||||||
//Cookie 认证
|
|
||||||
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
|
|
||||||
|
|
||||||
//绑定整个对象到Model上
|
//绑定整个对象到Model上
|
||||||
services.Configure<OptionsSetting>(Configuration);
|
services.Configure<OptionsSetting>(Configuration);
|
||||||
|
services.Configure<JwtSettings>(Configuration);
|
||||||
|
var jwtSettings = new JwtSettings();
|
||||||
|
Configuration.Bind("JwtSettings", jwtSettings);
|
||||||
|
|
||||||
|
//Cookie 认证
|
||||||
|
services.AddAuthentication(options =>
|
||||||
|
{
|
||||||
|
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
}).AddCookie()
|
||||||
|
.AddJwtBearer(o =>
|
||||||
|
{
|
||||||
|
o.TokenValidationParameters = JwtUtil.ValidParameters();
|
||||||
|
});
|
||||||
|
|
||||||
InjectRepositories(services);
|
InjectRepositories(services);
|
||||||
|
|
||||||
@ -78,11 +91,11 @@ namespace ZR.Admin.WebApi
|
|||||||
services.AddSwaggerGen(c =>
|
services.AddSwaggerGen(c =>
|
||||||
{
|
{
|
||||||
c.SwaggerDoc("v1", new OpenApiInfo { Title = "ZrAdmin", Version = "v1" });
|
c.SwaggerDoc("v1", new OpenApiInfo { Title = "ZrAdmin", Version = "v1" });
|
||||||
if (CurrentEnvironment.IsDevelopment())
|
//if (CurrentEnvironment.IsDevelopment())
|
||||||
{
|
//{
|
||||||
//添加文档注释
|
//添加文档注释
|
||||||
c.IncludeXmlComments("ZRAdmin.xml", true);
|
c.IncludeXmlComments(Path.Combine(CurrentEnvironment.ContentRootPath, "ZRAdmin.xml"), true);
|
||||||
}
|
//}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -112,7 +125,9 @@ namespace ZR.Admin.WebApi
|
|||||||
//app.UseAuthentication会启用Authentication中间件,该中间件会根据当前Http请求中的Cookie信息来设置HttpContext.User属性(后面会用到),
|
//app.UseAuthentication会启用Authentication中间件,该中间件会根据当前Http请求中的Cookie信息来设置HttpContext.User属性(后面会用到),
|
||||||
//所以只有在app.UseAuthentication方法之后注册的中间件才能够从HttpContext.User中读取到值,
|
//所以只有在app.UseAuthentication方法之后注册的中间件才能够从HttpContext.User中读取到值,
|
||||||
//这也是为什么上面强调app.UseAuthentication方法一定要放在下面的app.UseMvc方法前面,因为只有这样ASP.NET Core的MVC中间件中才能读取到HttpContext.User的值。
|
//这也是为什么上面强调app.UseAuthentication方法一定要放在下面的app.UseMvc方法前面,因为只有这样ASP.NET Core的MVC中间件中才能读取到HttpContext.User的值。
|
||||||
|
//1.先开启认证
|
||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
|
//2.再开启授权
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
app.UseSession();
|
app.UseSession();
|
||||||
app.UseResponseCaching();
|
app.UseResponseCaching();
|
||||||
|
|||||||
@ -15,9 +15,14 @@
|
|||||||
"urls": "http://localhost:8888", //项目启动url
|
"urls": "http://localhost:8888", //项目启动url
|
||||||
"sysConfig": {
|
"sysConfig": {
|
||||||
"DBCommandTimeout": 10,
|
"DBCommandTimeout": 10,
|
||||||
"tokenExpire": 1440, //Jwt token超时时间(分)
|
|
||||||
"cors": "http://localhost:8887" //跨域地址,多个用","隔开
|
"cors": "http://localhost:8887" //跨域地址,多个用","隔开
|
||||||
},
|
},
|
||||||
|
"JwtSettings": {
|
||||||
|
"Issuer": "https://localhost:8888",
|
||||||
|
"Audience": "https://localhost:8888",
|
||||||
|
"SecretKey": "Hello-key-ZRADMIN.NET-20210101",
|
||||||
|
"Expire": 5
|
||||||
|
},
|
||||||
"DemoMode": false, //是否演示模式
|
"DemoMode": false, //是否演示模式
|
||||||
"DbKey": "", //数据库加密key
|
"DbKey": "", //数据库加密key
|
||||||
"Upload": {
|
"Upload": {
|
||||||
@ -30,7 +35,7 @@
|
|||||||
"KEY": "XX",
|
"KEY": "XX",
|
||||||
"SECRET": "XX",
|
"SECRET": "XX",
|
||||||
"bucketName": "bucketName",
|
"bucketName": "bucketName",
|
||||||
"domainUrl": "http://xxx.xxx.com"//访问资源域名
|
"domainUrl": "http://xxx.xxx.com" //·ÃÎÊ×ÊÔ´ÓòÃû
|
||||||
},
|
},
|
||||||
"gen": {
|
"gen": {
|
||||||
"conn": "server=LAPTOP-STKF2M8H\\SQLEXPRESS;user=zr;pwd=abc;database=ZrAdmin;Trusted_Connection=SSPI",
|
"conn": "server=LAPTOP-STKF2M8H\\SQLEXPRESS;user=zr;pwd=abc;database=ZrAdmin;Trusted_Connection=SSPI",
|
||||||
|
|||||||
@ -1,11 +1,17 @@
|
|||||||
import router from './router'
|
import router from './router'
|
||||||
import store from './store'
|
import store from './store'
|
||||||
import { Message } from 'element-ui'
|
import {
|
||||||
|
Message
|
||||||
|
} from 'element-ui'
|
||||||
import NProgress from 'nprogress'
|
import NProgress from 'nprogress'
|
||||||
import 'nprogress/nprogress.css'
|
import 'nprogress/nprogress.css'
|
||||||
import { getToken } from '@/utils/auth'
|
import {
|
||||||
|
getToken
|
||||||
|
} from '@/utils/auth'
|
||||||
|
|
||||||
NProgress.configure({ showSpinner: false })
|
NProgress.configure({
|
||||||
|
showSpinner: false
|
||||||
|
})
|
||||||
|
|
||||||
const whiteList = ['/login', '/auth-redirect', '/bind', '/register', '/demo']
|
const whiteList = ['/login', '/auth-redirect', '/bind', '/register', '/demo']
|
||||||
|
|
||||||
@ -17,7 +23,9 @@ router.beforeEach((to, from, next) => {
|
|||||||
if (hasToken) {
|
if (hasToken) {
|
||||||
/* has token*/
|
/* has token*/
|
||||||
if (to.path === '/login') {
|
if (to.path === '/login') {
|
||||||
next({ path: '/' })
|
next({
|
||||||
|
path: '/'
|
||||||
|
})
|
||||||
NProgress.done()
|
NProgress.done()
|
||||||
} else {
|
} else {
|
||||||
if (store.getters.roles.length === 0) {
|
if (store.getters.roles.length === 0) {
|
||||||
@ -27,21 +35,28 @@ router.beforeEach((to, from, next) => {
|
|||||||
//console.log('拉取userInfo', JSON.stringify(res))
|
//console.log('拉取userInfo', JSON.stringify(res))
|
||||||
// 拉取user_info
|
// 拉取user_info
|
||||||
const roles = res.data.roles
|
const roles = res.data.roles
|
||||||
store.dispatch('GenerateRoutes', { roles }).then(accessRoutes => {
|
store.dispatch('GenerateRoutes', {
|
||||||
|
roles
|
||||||
|
}).then(accessRoutes => {
|
||||||
|
|
||||||
// 测试 默认静态页面
|
// 测试 默认静态页面
|
||||||
// store.dispatch('permission/generateRoutes', { roles }).then(accessRoutes => {
|
// store.dispatch('permission/generateRoutes', { roles }).then(accessRoutes => {
|
||||||
// 根据roles权限生成可访问的路由表
|
// 根据roles权限生成可访问的路由表
|
||||||
router.addRoutes(accessRoutes) // 动态添加可访问路由表
|
router.addRoutes(accessRoutes) // 动态添加可访问路由表
|
||||||
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
|
next({
|
||||||
|
...to,
|
||||||
|
replace: true
|
||||||
|
}) // hack方法 确保addRoutes已完成
|
||||||
})
|
})
|
||||||
next()
|
next()
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
//这部不能少,否则会出现死循环
|
//这部不能少,否则会出现死循环
|
||||||
store.dispatch('FedLogOut').then(() => {
|
store.dispatch('FedLogOut').then(() => {
|
||||||
Message.error(err)
|
Message.error(err != undefined ? err : '登录失败')
|
||||||
next({ path: '/' })
|
next({
|
||||||
|
path: '/'
|
||||||
|
})
|
||||||
})
|
})
|
||||||
next(`/login?redirect=${to.path}`)
|
next(`/login?redirect=${to.path}`)
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { MessageBox, Message } from 'element-ui'
|
import {
|
||||||
|
MessageBox,
|
||||||
|
Message
|
||||||
|
} from 'element-ui'
|
||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
import { getToken } from '@/utils/auth'
|
import {
|
||||||
|
getToken
|
||||||
|
} from '@/utils/auth'
|
||||||
// import errorCode from '@/utils/errorCode'
|
// import errorCode from '@/utils/errorCode'
|
||||||
|
|
||||||
// 解决后端跨域获取不到cookie问题
|
// 解决后端跨域获取不到cookie问题
|
||||||
@ -18,15 +23,9 @@ const service = axios.create({
|
|||||||
// request拦截器
|
// request拦截器
|
||||||
service.interceptors.request.use(config => {
|
service.interceptors.request.use(config => {
|
||||||
// 是否需要设置 token
|
// 是否需要设置 token
|
||||||
// const isToken = (config.headers || {}).isToken === false
|
|
||||||
// if (getToken() && !isToken) {
|
|
||||||
// config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
|
|
||||||
// }
|
|
||||||
// return config
|
|
||||||
// console.log(store.getters)
|
|
||||||
if (getToken()) {
|
if (getToken()) {
|
||||||
//将token放到请求头发送给服务器,将tokenkey放在请求头中
|
//将token放到请求头发送给服务器,将tokenkey放在请求头中
|
||||||
config.headers.Token = getToken();
|
config.headers['Authorization'] = 'Bearer ' + getToken();
|
||||||
} else {
|
} else {
|
||||||
// console.log(config)
|
// console.log(config)
|
||||||
}
|
}
|
||||||
@ -38,50 +37,47 @@ service.interceptors.request.use(config => {
|
|||||||
|
|
||||||
// 响应拦截器
|
// 响应拦截器
|
||||||
service.interceptors.response.use(res => {
|
service.interceptors.response.use(res => {
|
||||||
if (res.status !== 200) {
|
if (res.status !== 200) {
|
||||||
Promise.reject('network error');
|
Promise.reject('network error');
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
// 未设置状态码则默认成功状态
|
|
||||||
const code = res.data.code;
|
|
||||||
const msg = res.data.msg;
|
|
||||||
|
|
||||||
if (code == 401) {
|
|
||||||
MessageBox.confirm('登录状态已过期,请重新登录', '系统提示', {
|
|
||||||
confirmButtonText: '重新登录',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}
|
}
|
||||||
).then(() => {
|
// 未设置状态码则默认成功状态
|
||||||
store.dispatch('LogOut').then(() => {
|
const code = res.data.code;
|
||||||
location.href = '/index';
|
const msg = res.data.msg;
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
return Promise.reject()
|
if (code == 401) {
|
||||||
}
|
MessageBox.confirm('登录状态已过期,请重新登录', '系统提示', {
|
||||||
else if (code == 0 || code == 110 || code == 101 || code == 403 || code == 500) {
|
confirmButtonText: '重新登录',
|
||||||
Message({
|
cancelButtonText: '取消',
|
||||||
message: msg,
|
type: 'warning'
|
||||||
type: 'error'
|
}).then(() => {
|
||||||
})
|
store.dispatch('LogOut').then(() => {
|
||||||
return Promise.reject()
|
location.href = '/index';
|
||||||
}
|
})
|
||||||
else {
|
})
|
||||||
//返回标准 code/msg/data字段
|
|
||||||
return res.data;
|
return Promise.reject()
|
||||||
}
|
} else if (code == 0 || code == 110 || code == 101 || code == 403 || code == 500) {
|
||||||
},
|
Message({
|
||||||
|
message: msg,
|
||||||
|
type: 'error'
|
||||||
|
})
|
||||||
|
return Promise.reject()
|
||||||
|
} else {
|
||||||
|
//返回标准 code/msg/data字段
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
},
|
||||||
error => {
|
error => {
|
||||||
console.log('err' + error)
|
console.log('err' + error)
|
||||||
let { message } = error;
|
let {
|
||||||
|
message
|
||||||
|
} = error;
|
||||||
if (message == "Network Error") {
|
if (message == "Network Error") {
|
||||||
message = "后端接口连接异常";
|
message = "后端接口连接异常";
|
||||||
}
|
} else if (message.includes("timeout")) {
|
||||||
else if (message.includes("timeout")) {
|
|
||||||
message = "系统接口请求超时";
|
message = "系统接口请求超时";
|
||||||
}
|
} else if (message.includes("Request failed with status code")) {
|
||||||
else if (message.includes("Request failed with status code")) {
|
|
||||||
message = "系统接口" + message.substr(message.length - 3) + "异常";
|
message = "系统接口" + message.substr(message.length - 3) + "异常";
|
||||||
}
|
}
|
||||||
Message({
|
Message({
|
||||||
@ -129,10 +125,10 @@ export function post(url, params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 提交表单
|
* 提交表单
|
||||||
* @param {*} url
|
* @param {*} url
|
||||||
* @param {*} data
|
* @param {*} data
|
||||||
*/
|
*/
|
||||||
export function postForm(url, data, config) {
|
export function postForm(url, data, config) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
axios.post(url, data, config).then(res => {
|
axios.post(url, data, config).then(res => {
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export function downLoadZip(str, filename) {
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
url: str,
|
url: str,
|
||||||
responseType: 'blob',
|
responseType: 'blob',
|
||||||
headers: { 'Token': getToken() }
|
headers: { 'Authorization': 'Bearer ' + getToken() }
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
resolveBlob(res, mimeMap.zip)
|
resolveBlob(res, mimeMap.zip)
|
||||||
})
|
})
|
||||||
@ -25,7 +25,7 @@ export function downLoadExcel(str, filename) {
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
url: url,
|
url: url,
|
||||||
responseType: 'blob',
|
responseType: 'blob',
|
||||||
headers: { 'Token': getToken() }
|
headers: { 'Authorization': 'Bearer ' + getToken() }
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
resolveExcel(res, filename)
|
resolveExcel(res, filename)
|
||||||
})
|
})
|
||||||
|
|||||||
@ -273,7 +273,7 @@ export default {
|
|||||||
// 是否更新已经存在的用户数据
|
// 是否更新已经存在的用户数据
|
||||||
updateSupport: 0,
|
updateSupport: 0,
|
||||||
// 设置上传的请求头部
|
// 设置上传的请求头部
|
||||||
headers: { Authorization: getToken() },
|
headers: { Authorization: 'Bearer ' + getToken() },
|
||||||
// 上传的地址
|
// 上传的地址
|
||||||
url: process.env.VUE_APP_BASE_API + "system/user/importData",
|
url: process.env.VUE_APP_BASE_API + "system/user/importData",
|
||||||
},
|
},
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
<el-input v-model="form.subject"></el-input>
|
<el-input v-model="form.subject"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="邮件内容" prop="content">
|
<el-form-item label="邮件内容" prop="content">
|
||||||
<editor v-model="form.content" :min-height="192" />
|
<editor v-model="form.content" :min-height="192" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="附件">
|
<el-form-item label="附件">
|
||||||
@ -37,7 +37,7 @@ export default {
|
|||||||
fileUrl: "",
|
fileUrl: "",
|
||||||
},
|
},
|
||||||
headers: {
|
headers: {
|
||||||
Token: "",
|
Authorization: "Bearer " + getToken(),
|
||||||
},
|
},
|
||||||
uploadActionUrl: process.env.VUE_APP_BASE_API + "upload/SaveFile",
|
uploadActionUrl: process.env.VUE_APP_BASE_API + "upload/SaveFile",
|
||||||
rules: {
|
rules: {
|
||||||
@ -55,7 +55,6 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.headers.Token = getToken();
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 表单重置
|
// 表单重置
|
||||||
@ -106,7 +105,7 @@ export default {
|
|||||||
loading.close();
|
loading.close();
|
||||||
}, 5000);
|
}, 5000);
|
||||||
} else {
|
} else {
|
||||||
console.log('未通过')
|
console.log("未通过");
|
||||||
//校验不通过
|
//校验不通过
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user