add
This commit is contained in:
@ -15,6 +15,14 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class SecurityConstant {
|
public class SecurityConstant {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 被挤下线
|
||||||
|
*/
|
||||||
|
public static final int HTTP_SQUEEZED_OFFLINE = 4011;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static final int MAX_ERROR_COUNT = 5;
|
public static final int MAX_ERROR_COUNT = 5;
|
||||||
public static final String LOGOUT_URL = "/logout";
|
public static final String LOGOUT_URL = "/logout";
|
||||||
public static final String HAS_BEEN_PULLED_BLACK = "您的IP已经被系统拉黑";
|
public static final String HAS_BEEN_PULLED_BLACK = "您的IP已经被系统拉黑";
|
||||||
@ -31,6 +39,7 @@ public class SecurityConstant {
|
|||||||
public static final String REDIS_SECRET_KEY = "sys:secret:secret";
|
public static final String REDIS_SECRET_KEY = "sys:secret:secret";
|
||||||
public static final String USER_DETAILS_REDIS_KEY = "user_details:";
|
public static final String USER_DETAILS_REDIS_KEY = "user_details:";
|
||||||
public static final String ONLINE_USER_REDIS_KEY = "online_user:";
|
public static final String ONLINE_USER_REDIS_KEY = "online_user:";
|
||||||
|
public static final String LOGGED_USER_REDIS_KEY = "logged_user:";
|
||||||
public static final String TOKEN_EXPIRE_TIME_KEY = ConfigConstant.SYS_CONFIG_KEY_PREFIX + "sys.token.expireTime";
|
public static final String TOKEN_EXPIRE_TIME_KEY = ConfigConstant.SYS_CONFIG_KEY_PREFIX + "sys.token.expireTime";
|
||||||
/**
|
/**
|
||||||
* 登录成功
|
* 登录成功
|
||||||
|
@ -23,6 +23,10 @@ public class LoginUser implements UserDetails {
|
|||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备号 暂用UUID
|
||||||
|
*/
|
||||||
|
private String deviceSn;
|
||||||
/**
|
/**
|
||||||
* 用户ID
|
* 用户ID
|
||||||
*/
|
*/
|
||||||
@ -70,6 +74,14 @@ public class LoginUser implements UserDetails {
|
|||||||
this.roles = roles;
|
this.roles = roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDeviceSn() {
|
||||||
|
return deviceSn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceSn(String deviceSn) {
|
||||||
|
this.deviceSn = deviceSn;
|
||||||
|
}
|
||||||
|
|
||||||
public List<RoleDto> getRoles() {
|
public List<RoleDto> getRoles() {
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,11 @@ public class OnlineUser implements Serializable {
|
|||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备号 暂用UUID
|
||||||
|
*/
|
||||||
|
private String deviceSn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录账号
|
* 登录账号
|
||||||
*/
|
*/
|
||||||
|
@ -3,6 +3,7 @@ package com.qiaoba.auth.filters;
|
|||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.qiaoba.auth.constants.SecurityConstant;
|
import com.qiaoba.auth.constants.SecurityConstant;
|
||||||
import com.qiaoba.auth.entity.OnlineUser;
|
import com.qiaoba.auth.entity.OnlineUser;
|
||||||
|
import com.qiaoba.auth.properties.AuthConfigProperties;
|
||||||
import com.qiaoba.auth.service.OnlineUserService;
|
import com.qiaoba.auth.service.OnlineUserService;
|
||||||
import com.qiaoba.auth.utils.TokenUtil;
|
import com.qiaoba.auth.utils.TokenUtil;
|
||||||
import com.qiaoba.common.web.utils.ResponseUtil;
|
import com.qiaoba.common.web.utils.ResponseUtil;
|
||||||
@ -34,26 +35,31 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
|
|||||||
|
|
||||||
private final UserDetailsService userDetailsService;
|
private final UserDetailsService userDetailsService;
|
||||||
private final OnlineUserService onlineUserService;
|
private final OnlineUserService onlineUserService;
|
||||||
|
private final AuthConfigProperties authConfigProperties;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doFilterInternal(HttpServletRequest request,
|
protected void doFilterInternal(HttpServletRequest request,
|
||||||
HttpServletResponse response,
|
HttpServletResponse response,
|
||||||
FilterChain chain) throws ServletException, IOException {
|
FilterChain chain) throws ServletException, IOException {
|
||||||
|
|
||||||
|
if (authConfigProperties.getWhitelist().contains(request.getRequestURI())) {
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 取Header中的Token
|
// 取Header中的Token
|
||||||
String authHeader = request.getHeader(SecurityConstant.TOKEN_HEADER);
|
String authHeader = request.getHeader(SecurityConstant.TOKEN_HEADER);
|
||||||
if (StrUtil.isNotBlank(authHeader) && authHeader.startsWith(SecurityConstant.TOKEN_HEAD)) {
|
if (StrUtil.isNotBlank(authHeader) && authHeader.startsWith(SecurityConstant.TOKEN_HEAD)) {
|
||||||
String authToken = authHeader.substring(SecurityConstant.TOKEN_HEAD.length());
|
String authToken = authHeader.substring(SecurityConstant.TOKEN_HEAD.length());
|
||||||
// todo
|
// todo
|
||||||
String username1 = "admin";
|
/* String username1 = "admin";
|
||||||
OnlineUser onlineUser = onlineUserService.selectByUsername(username1);
|
OnlineUser onlineUser = onlineUserService.selectByUsername(username1);
|
||||||
if (Objects.isNull(onlineUser)) {
|
if (Objects.isNull(onlineUser)) {
|
||||||
// todo 返回401
|
ResponseUtil.errorAuth(response, 4011, "暂无登录");
|
||||||
ResponseUtil.response(response, "");
|
|
||||||
return;
|
return;
|
||||||
}
|
}*/
|
||||||
// 续期有效期
|
// 续期有效期
|
||||||
onlineUserService.insert(onlineUser);
|
//onlineUserService.insert(onlineUser);
|
||||||
if (TokenUtil.validateToken(authToken)) {
|
if (TokenUtil.validateToken(authToken)) {
|
||||||
String username = TokenUtil.getUserNameFromToken(authToken);
|
String username = TokenUtil.getUserNameFromToken(authToken);
|
||||||
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
|
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
package com.qiaoba.auth.handler;
|
package com.qiaoba.auth.handler;
|
||||||
|
|
||||||
import cn.hutool.http.HttpStatus;
|
import cn.hutool.http.HttpStatus;
|
||||||
import cn.hutool.json.JSONUtil;
|
|
||||||
import com.qiaoba.auth.constants.SecurityConstant;
|
import com.qiaoba.auth.constants.SecurityConstant;
|
||||||
import com.qiaoba.common.base.result.AjaxResult;
|
|
||||||
import com.qiaoba.common.web.utils.ResponseUtil;
|
import com.qiaoba.common.web.utils.ResponseUtil;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
@ -25,7 +23,6 @@ import java.io.IOException;
|
|||||||
public class AccessDeniedHandler implements AuthenticationEntryPoint {
|
public class AccessDeniedHandler implements AuthenticationEntryPoint {
|
||||||
@Override
|
@Override
|
||||||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
|
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
|
||||||
AjaxResult result = AjaxResult.error(HttpStatus.HTTP_UNAUTHORIZED, SecurityConstant.ACCESS_DENIED);
|
ResponseUtil.errorAuth(response, HttpStatus.HTTP_UNAUTHORIZED, SecurityConstant.ACCESS_DENIED);
|
||||||
ResponseUtil.response(response, JSONUtil.toJsonStr(result));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package com.qiaoba.auth.handler;
|
package com.qiaoba.auth.handler;
|
||||||
|
|
||||||
|
import com.qiaoba.auth.constants.SecurityConstant;
|
||||||
import com.qiaoba.auth.entity.LoginUser;
|
import com.qiaoba.auth.entity.LoginUser;
|
||||||
|
import com.qiaoba.auth.service.OnlineUserService;
|
||||||
import com.qiaoba.common.redis.service.RedisService;
|
import com.qiaoba.common.redis.service.RedisService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
@ -24,11 +26,13 @@ import java.io.IOException;
|
|||||||
public class LogoutHandler implements LogoutSuccessHandler {
|
public class LogoutHandler implements LogoutSuccessHandler {
|
||||||
|
|
||||||
private final RedisService redisService;
|
private final RedisService redisService;
|
||||||
|
private final OnlineUserService onlineUserService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
|
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
|
||||||
// 删除缓存中的用户信息
|
// 删除缓存中的用户信息
|
||||||
LoginUser user = (LoginUser) authentication.getPrincipal();
|
LoginUser user = (LoginUser) authentication.getPrincipal();
|
||||||
redisService.del(user.getUserId());
|
redisService.del(SecurityConstant.USER_DETAILS_REDIS_KEY + user.getUsername());
|
||||||
|
onlineUserService.deleteOne(user.getUsername(), user.getDeviceSn());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,16 +24,25 @@ public interface OnlineUserService {
|
|||||||
* 删除(强退)
|
* 删除(强退)
|
||||||
*
|
*
|
||||||
* @param username 登录账号
|
* @param username 登录账号
|
||||||
|
* @param deviceSn 设备号
|
||||||
*/
|
*/
|
||||||
void delete(String username);
|
void deleteOne(String username, String deviceSn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除(强退)
|
||||||
|
*
|
||||||
|
* @param username 登录账号
|
||||||
|
*/
|
||||||
|
void deleteAll(String username);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询
|
* 查询
|
||||||
*
|
*
|
||||||
* @param username 登录账号
|
* @param username 登录账号
|
||||||
|
* @param deviceSn deviceSn
|
||||||
* @return 在线用户
|
* @return 在线用户
|
||||||
*/
|
*/
|
||||||
OnlineUser selectByUsername(String username);
|
OnlineUser selectOne(String username, String deviceSn);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量查询
|
* 批量查询
|
||||||
@ -42,4 +51,6 @@ public interface OnlineUserService {
|
|||||||
* @return list
|
* @return list
|
||||||
*/
|
*/
|
||||||
List<OnlineUser> selectList(String username);
|
List<OnlineUser> selectList(String username);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,18 +27,26 @@ public class OnlineUserServiceImpl implements OnlineUserService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void insert(OnlineUser onlineUser) {
|
public void insert(OnlineUser onlineUser) {
|
||||||
redisService.set(handleKey(onlineUser.getUsername()), onlineUser, TokenUtil.expireTime * 3600);
|
// key: username
|
||||||
|
// hashKey: deviceSn
|
||||||
|
// value: onlineUser
|
||||||
|
redisService.hSet(handleKey(onlineUser.getUsername()), onlineUser.getDeviceSn(), onlineUser, TokenUtil.expireTime * 3600);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete(String username) {
|
public void deleteOne(String username, String deviceSn) {
|
||||||
|
redisService.hDel(handleKey(username), deviceSn);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteAll(String username) {
|
||||||
redisService.del(handleKey(username));
|
redisService.del(handleKey(username));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OnlineUser selectByUsername(String username) {
|
public OnlineUser selectOne(String username, String deviceSn) {
|
||||||
if (redisService.hasKey(handleKey(username))) {
|
if (redisService.hHasKey(username, deviceSn)) {
|
||||||
return redisService.getObject(handleKey(username), OnlineUser.class);
|
return redisService.hGetObject(username, deviceSn, OnlineUser.class);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -5,4 +5,5 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
|||||||
com.qiaoba.auth.filters.JwtAuthenticationTokenFilter,\
|
com.qiaoba.auth.filters.JwtAuthenticationTokenFilter,\
|
||||||
com.qiaoba.auth.advice.SecurityExceptionAdvice,\
|
com.qiaoba.auth.advice.SecurityExceptionAdvice,\
|
||||||
com.qiaoba.auth.aspectj.DataScopeAspect,\
|
com.qiaoba.auth.aspectj.DataScopeAspect,\
|
||||||
|
com.qiaoba.auth.service.impl.OnlineUserServiceImpl,\
|
||||||
com.qiaoba.auth.config.SpringSecurityConfig
|
com.qiaoba.auth.config.SpringSecurityConfig
|
||||||
|
@ -354,4 +354,15 @@ public interface RedisService {
|
|||||||
* @return // List<clazz>
|
* @return // List<clazz>
|
||||||
*/
|
*/
|
||||||
<T> List<T> getObjectList(String key, Class<T> clazz);
|
<T> List<T> getObjectList(String key, Class<T> clazz);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hGetObject
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param hashKey hashKey
|
||||||
|
* @param clazz clazz
|
||||||
|
* @param <T> T
|
||||||
|
* @return clazz
|
||||||
|
*/
|
||||||
|
<T> T hGetObject(String key, String hashKey, Class<T> clazz);
|
||||||
}
|
}
|
||||||
|
@ -229,6 +229,12 @@ public class RedisServiceImpl implements RedisService {
|
|||||||
return (List<T>) get(key);
|
return (List<T>) get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> T hGetObject(String key, String hashKey, Class<T> clazz) {
|
||||||
|
return (T) hGet(key, hashKey);
|
||||||
|
}
|
||||||
|
|
||||||
private String handleKey(String key) {
|
private String handleKey(String key) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("tenant_").append(BaseContext.getTenantId()).append(":").append(key);
|
sb.append("tenant_").append(BaseContext.getTenantId()).append(":").append(key);
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package com.qiaoba.common.web.utils;
|
package com.qiaoba.common.web.utils;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.qiaoba.common.base.result.AjaxResult;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@ -18,4 +21,8 @@ public class ResponseUtil {
|
|||||||
response.getWriter().write(msg);
|
response.getWriter().write(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void errorAuth(HttpServletResponse response, Integer code, String msg) throws IOException {
|
||||||
|
AjaxResult result = AjaxResult.error(code, msg);
|
||||||
|
response(response, JSONUtil.toJsonStr(result));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import com.qiaoba.auth.constants.SecurityConstant;
|
|||||||
import com.qiaoba.auth.entity.LoginUser;
|
import com.qiaoba.auth.entity.LoginUser;
|
||||||
import com.qiaoba.auth.entity.SecurityUser;
|
import com.qiaoba.auth.entity.SecurityUser;
|
||||||
import com.qiaoba.auth.entity.dto.RoleDto;
|
import com.qiaoba.auth.entity.dto.RoleDto;
|
||||||
|
import com.qiaoba.auth.utils.TokenUtil;
|
||||||
import com.qiaoba.common.base.enums.BaseEnum;
|
import com.qiaoba.common.base.enums.BaseEnum;
|
||||||
import com.qiaoba.common.redis.service.RedisService;
|
import com.qiaoba.common.redis.service.RedisService;
|
||||||
import com.qiaoba.module.system.service.SysMenuService;
|
import com.qiaoba.module.system.service.SysMenuService;
|
||||||
@ -62,7 +63,7 @@ public class SysUserDetailsServiceImpl implements UserDetailsService, SysUserDet
|
|||||||
SysUser user = sysUserService.selectByUsername(username);
|
SysUser user = sysUserService.selectByUsername(username);
|
||||||
UserDetails details = createUserDetails(user);
|
UserDetails details = createUserDetails(user);
|
||||||
SecurityUser securityUser = BeanUtil.copyProperties(details, SecurityUser.class);
|
SecurityUser securityUser = BeanUtil.copyProperties(details, SecurityUser.class);
|
||||||
redisService.set(SecurityConstant.USER_DETAILS_REDIS_KEY + username, securityUser);
|
redisService.set(SecurityConstant.USER_DETAILS_REDIS_KEY + username, securityUser, TokenUtil.expireTime * 3600);
|
||||||
return details;
|
return details;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user