40 changed files with 715 additions and 192 deletions
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
package com.ruoyi.common.core.constant; |
||||
|
||||
/** |
||||
* Token的Key常量 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class TokenConstants |
||||
{ |
||||
/** |
||||
* 令牌自定义标识 |
||||
*/ |
||||
public static final String AUTHENTICATION = "Authorization"; |
||||
|
||||
/** |
||||
* 令牌前缀 |
||||
*/ |
||||
public static final String PREFIX = "Bearer "; |
||||
|
||||
/** |
||||
* 令牌秘钥 |
||||
*/ |
||||
public final static String SECRET = "abcdefghijklmnopqrstuvwxyz"; |
||||
|
||||
} |
@ -0,0 +1,88 @@
@@ -0,0 +1,88 @@
|
||||
package com.ruoyi.common.core.context; |
||||
|
||||
import java.util.Map; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
import com.alibaba.ttl.TransmittableThreadLocal; |
||||
import com.ruoyi.common.core.constant.SecurityConstants; |
||||
import com.ruoyi.common.core.text.Convert; |
||||
import com.ruoyi.common.core.utils.StringUtils; |
||||
|
||||
/** |
||||
* 获取当前线程变量中的 用户id、用户名称、Token等信息 |
||||
* 注意: 必须在网关通过请求头的方法传入,同时在HeaderInterceptor拦截器设置值。 否则这里无法获取 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class SecurityContextHolder |
||||
{ |
||||
private static final TransmittableThreadLocal<Map<String, Object>> THREAD_LOCAL = new TransmittableThreadLocal<>(); |
||||
|
||||
public static void set(String key, Object value) |
||||
{ |
||||
Map<String, Object> map = getLocalMap(); |
||||
map.put(key, value == null ? StringUtils.EMPTY : value); |
||||
} |
||||
|
||||
public static String get(String key) |
||||
{ |
||||
Map<String, Object> map = getLocalMap(); |
||||
return Convert.toStr(map.getOrDefault(key, StringUtils.EMPTY)); |
||||
} |
||||
|
||||
public static <T> T get(String key, Class<T> clazz) |
||||
{ |
||||
Map<String, Object> map = getLocalMap(); |
||||
return StringUtils.cast(map.getOrDefault(key, null)); |
||||
} |
||||
|
||||
public static Map<String, Object> getLocalMap() |
||||
{ |
||||
Map<String, Object> map = THREAD_LOCAL.get(); |
||||
if (map == null) |
||||
{ |
||||
map = new ConcurrentHashMap<String, Object>(); |
||||
THREAD_LOCAL.set(map); |
||||
} |
||||
return map; |
||||
} |
||||
|
||||
public static void setLocalMap(Map<String, Object> threadLocalMap) |
||||
{ |
||||
THREAD_LOCAL.set(threadLocalMap); |
||||
} |
||||
|
||||
public static Long getUserId() |
||||
{ |
||||
return Convert.toLong(get(SecurityConstants.DETAILS_USER_ID), 0L); |
||||
} |
||||
|
||||
public static void setUserId(String account) |
||||
{ |
||||
set(SecurityConstants.DETAILS_USER_ID, account); |
||||
} |
||||
|
||||
public static String getUserName() |
||||
{ |
||||
return get(SecurityConstants.DETAILS_USERNAME); |
||||
} |
||||
|
||||
public static void setUserName(String username) |
||||
{ |
||||
set(SecurityConstants.DETAILS_USERNAME, username); |
||||
} |
||||
|
||||
public static String getUserKey() |
||||
{ |
||||
return get(SecurityConstants.USER_KEY); |
||||
} |
||||
|
||||
public static void setUserKey(String userKey) |
||||
{ |
||||
set(SecurityConstants.USER_KEY, userKey); |
||||
} |
||||
|
||||
public static void remove() |
||||
{ |
||||
THREAD_LOCAL.remove(); |
||||
} |
||||
} |
@ -0,0 +1,123 @@
@@ -0,0 +1,123 @@
|
||||
package com.ruoyi.common.core.utils; |
||||
|
||||
import java.util.Map; |
||||
import com.ruoyi.common.core.constant.SecurityConstants; |
||||
import com.ruoyi.common.core.constant.TokenConstants; |
||||
import com.ruoyi.common.core.text.Convert; |
||||
import io.jsonwebtoken.Claims; |
||||
import io.jsonwebtoken.Jwts; |
||||
import io.jsonwebtoken.SignatureAlgorithm; |
||||
|
||||
/** |
||||
* Jwt工具类 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class JwtUtils |
||||
{ |
||||
public static String secret = TokenConstants.SECRET; |
||||
|
||||
/** |
||||
* 从数据声明生成令牌 |
||||
* |
||||
* @param claims 数据声明 |
||||
* @return 令牌 |
||||
*/ |
||||
public static String createToken(Map<String, Object> claims) |
||||
{ |
||||
String token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, secret).compact(); |
||||
return token; |
||||
} |
||||
|
||||
/** |
||||
* 从令牌中获取数据声明 |
||||
* |
||||
* @param token 令牌 |
||||
* @return 数据声明 |
||||
*/ |
||||
public static Claims parseToken(String token) |
||||
{ |
||||
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody(); |
||||
} |
||||
|
||||
/** |
||||
* 根据令牌获取用户标识 |
||||
* |
||||
* @param token 令牌 |
||||
* @return 用户ID |
||||
*/ |
||||
public static String getUserKey(String token) |
||||
{ |
||||
Claims claims = parseToken(token); |
||||
return getValue(claims, SecurityConstants.USER_KEY); |
||||
} |
||||
|
||||
/** |
||||
* 根据令牌获取用户标识 |
||||
* |
||||
* @param claims 身份信息 |
||||
* @return 用户ID |
||||
*/ |
||||
public static String getUserKey(Claims claims) |
||||
{ |
||||
return getValue(claims, SecurityConstants.USER_KEY); |
||||
} |
||||
|
||||
/** |
||||
* 根据令牌获取用户ID |
||||
* |
||||
* @param token 令牌 |
||||
* @return 用户ID |
||||
*/ |
||||
public static String getUserId(String token) |
||||
{ |
||||
Claims claims = parseToken(token); |
||||
return getValue(claims, SecurityConstants.DETAILS_USER_ID); |
||||
} |
||||
|
||||
/** |
||||
* 根据身份信息获取用户ID |
||||
* |
||||
* @param claims 身份信息 |
||||
* @return 用户ID |
||||
*/ |
||||
public static String getUserId(Claims claims) |
||||
{ |
||||
return getValue(claims, SecurityConstants.DETAILS_USER_ID); |
||||
} |
||||
|
||||
/** |
||||
* 根据令牌获取用户名 |
||||
* |
||||
* @param token 令牌 |
||||
* @return 用户名 |
||||
*/ |
||||
public static String getUserName(String token) |
||||
{ |
||||
Claims claims = parseToken(token); |
||||
return getValue(claims, SecurityConstants.DETAILS_USERNAME); |
||||
} |
||||
|
||||
/** |
||||
* 根据身份信息获取用户名 |
||||
* |
||||
* @param claims 身份信息 |
||||
* @return 用户名 |
||||
*/ |
||||
public static String getUserName(Claims claims) |
||||
{ |
||||
return getValue(claims, SecurityConstants.DETAILS_USERNAME); |
||||
} |
||||
|
||||
/** |
||||
* 根据身份信息获取键值 |
||||
* |
||||
* @param claims 身份信息 |
||||
* @param key 键 |
||||
* @return 值 |
||||
*/ |
||||
public static String getValue(Claims claims, String key) |
||||
{ |
||||
return Convert.toStr(claims.get(key), ""); |
||||
} |
||||
} |
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
package com.ruoyi.common.security.config; |
||||
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; |
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; |
||||
import com.ruoyi.common.security.interceptor.HeaderInterceptor; |
||||
|
||||
/** |
||||
* 拦截器配置 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class WebMvcConfig implements WebMvcConfigurer |
||||
{ |
||||
/** 不需要拦截地址 */ |
||||
public static final String[] excludeUrls = { "/login", "/logout", "/refresh" }; |
||||
|
||||
@Override |
||||
public void addInterceptors(InterceptorRegistry registry) |
||||
{ |
||||
registry.addInterceptor(getHeaderInterceptor()) |
||||
.addPathPatterns("/**") |
||||
.excludePathPatterns(excludeUrls) |
||||
.order(-10); |
||||
} |
||||
|
||||
/** |
||||
* 自定义请求头拦截器 |
||||
*/ |
||||
public HeaderInterceptor getHeaderInterceptor() |
||||
{ |
||||
return new HeaderInterceptor(); |
||||
} |
||||
} |
@ -0,0 +1,53 @@
@@ -0,0 +1,53 @@
|
||||
package com.ruoyi.common.security.interceptor; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
import org.springframework.web.method.HandlerMethod; |
||||
import org.springframework.web.servlet.AsyncHandlerInterceptor; |
||||
import com.ruoyi.common.core.constant.SecurityConstants; |
||||
import com.ruoyi.common.core.context.SecurityContextHolder; |
||||
import com.ruoyi.common.core.utils.ServletUtils; |
||||
import com.ruoyi.common.core.utils.StringUtils; |
||||
import com.ruoyi.common.security.auth.AuthUtil; |
||||
import com.ruoyi.common.security.utils.SecurityUtils; |
||||
import com.ruoyi.system.api.model.LoginUser; |
||||
|
||||
/** |
||||
* 自定义请求头拦截器,将Header数据封装到线程变量中方便获取 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class HeaderInterceptor implements AsyncHandlerInterceptor |
||||
{ |
||||
@Override |
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception |
||||
{ |
||||
if (!(handler instanceof HandlerMethod)) |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
SecurityContextHolder.setUserId(ServletUtils.getHeader(request, SecurityConstants.DETAILS_USER_ID)); |
||||
SecurityContextHolder.setUserName(ServletUtils.getHeader(request, SecurityConstants.DETAILS_USERNAME)); |
||||
SecurityContextHolder.setUserKey(ServletUtils.getHeader(request, SecurityConstants.USER_KEY)); |
||||
|
||||
String token = SecurityUtils.getToken(); |
||||
if (StringUtils.isNotEmpty(token)) |
||||
{ |
||||
LoginUser loginUser = AuthUtil.getLoginUser(token); |
||||
if (StringUtils.isNotNull(loginUser)) |
||||
{ |
||||
AuthUtil.verifyLoginUserExpire(loginUser); |
||||
SecurityContextHolder.set(SecurityConstants.LOGIN_USER, loginUser); |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) |
||||
throws Exception |
||||
{ |
||||
SecurityContextHolder.remove(); |
||||
} |
||||
} |
Loading…
Reference in new issue