增加工具类

pull/1/head
caolin 2023-08-12 14:42:57 +08:00
parent df866d4d27
commit 38f92a9679
13 changed files with 377 additions and 31 deletions

View File

@ -16,7 +16,7 @@
<java.version>1.8</java.version> <java.version>1.8</java.version>
<mybatis-plus-boot-starter.version>3.3.0</mybatis-plus-boot-starter.version> <mybatis-plus-boot-starter.version>3.3.0</mybatis-plus-boot-starter.version>
<hutool.version>5.7.20</hutool.version> <hutool.version>5.7.20</hutool.version>
<knife4j-micro-spring-boot-starter.version>3.0.3</knife4j-micro-spring-boot-starter.version> <knife4j-spring-boot-starter.version>2.0.9</knife4j-spring-boot-starter.version>
</properties> </properties>
<dependencies> <dependencies>
@ -98,8 +98,8 @@
<dependency> <dependency>
<groupId>com.github.xiaoymin</groupId> <groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-micro-spring-boot-starter</artifactId> <artifactId>knife4j-spring-boot-starter</artifactId>
<version>${knife4j-micro-spring-boot-starter.version}</version> <version>${knife4j-spring-boot-starter.version}</version>
<exclusions> <exclusions>
<exclusion> <exclusion>
<groupId>javax.validation</groupId> <groupId>javax.validation</groupId>

View File

@ -0,0 +1,34 @@
package com.jwl.driver.server.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
*
*/
@ConfigurationProperties(prefix = AuthConfig.PREFIX)
@Component
@Data
public class AuthConfig {
public static final String PREFIX = "driver.auth-config";
/**
* preAuth trueurlnoAuthEndPoints
* falseurlneedAuthEndPoints
*/
private Boolean preAuth;
/**
* url
*/
private String[] noAuthEndPoints;
/**
* url
*/
private String[] needAuthEndPoints;
}

View File

@ -26,7 +26,8 @@ public class CorsConfig implements WebMvcConfigurer {
@Override @Override
public void addInterceptors(InterceptorRegistry registry) { public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor).addPathPatterns("/**").excludePathPatterns("/**/login", registry.addInterceptor(authInterceptor).addPathPatterns("/**").excludePathPatterns("/**/login",
// "/error", "/error",
"/webjars/**",
"/doc.html"); "/doc.html");
} }
@ -56,11 +57,6 @@ public class CorsConfig implements WebMvcConfigurer {
registry.addResourceHandler("doc.html") registry.addResourceHandler("doc.html")
.addResourceLocations("classpath:/META-INF/resources/"); .addResourceLocations("classpath:/META-INF/resources/");
/**
* swagger-ui
*/
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
/** 公共部分内容 */ /** 公共部分内容 */
registry.addResourceHandler("/webjars/**") registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/"); .addResourceLocations("classpath:/META-INF/resources/webjars/");

View File

@ -8,12 +8,11 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
/** /**
* <p> * <p>
@ -35,9 +34,17 @@ public class TdSysUserController {
@ApiOperation("用户登陆") @ApiOperation("用户登陆")
@PostMapping("/login") @PostMapping("/login")
public BaseResponse login(@RequestBody LoginUserDto loginUserDto) throws Exception { public BaseResponse login(@RequestBody LoginUserDto loginUserDto) {
log.info("用户登录======>loginUserDto:{}", loginUserDto); log.info("用户登录======>loginUserDto:{}", loginUserDto);
return BaseResponse.success(userService.login(loginUserDto)); return BaseResponse.success(userService.login(loginUserDto));
} }
@ApiOperation("用户登出")
@GetMapping("/loginOut")
public BaseResponse loginOut(){
log.info("用户登出======>{}", LocalDateTime.now());
return BaseResponse.success(userService.loginOut());
}
} }

View File

@ -0,0 +1,32 @@
package com.jwl.driver.server.dto;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class SecurityUser implements Serializable {
/**
*
*/
private Long userId;
/**
*
*/
private String userName;
/**
* token
*/
private String token;
}

View File

@ -0,0 +1,37 @@
package com.jwl.driver.server.filter;
import cn.hutool.core.util.StrUtil;
import com.jwl.driver.server.util.TokenThreadUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 线token
*/
@Component
public class TokenFilter extends OncePerRequestFilter {
private static final Logger log = LoggerFactory.getLogger(TokenFilter.class);
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String requestTokenHeader = request.getHeader("Authorization");
if (StrUtil.isBlank(requestTokenHeader)) {
log.warn("Bearer token 为空");
filterChain.doFilter((ServletRequest) request, (ServletResponse) response);
return;
}
TokenThreadUtil.setToken(requestTokenHeader);
filterChain.doFilter(request, response);
}
}

View File

@ -1,14 +1,23 @@
package com.jwl.driver.server.interceptor; package com.jwl.driver.server.interceptor;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import com.jwl.driver.server.config.AuthConfig;
import com.jwl.driver.server.constant.ErrorCode;
import com.jwl.driver.server.exception.BusinessException;
import com.jwl.driver.server.redis.RedisCache; import com.jwl.driver.server.redis.RedisCache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Objects; import java.util.Objects;
/** /**
@ -18,29 +27,62 @@ import java.util.Objects;
*/ */
@Component @Component
@Slf4j
public class AuthInterceptor implements HandlerInterceptor { public class AuthInterceptor implements HandlerInterceptor {
@Autowired @Autowired
private RedisCache redisCache; private RedisCache redisCache;
@Resource
private AuthConfig authConfig;
@Override @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestURI = request.getRequestURI(); String requestURI = request.getRequestURI();
if (requestURI.contains("doc.html")){
return true;
}
response.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8"); response.setContentType("text/html;charset=utf-8");
String token = request.getHeader("token"); String requestTokenHeader = request.getHeader("Authorization");
if (StringUtils.isEmpty(token)) {
response.getWriter().print("用户未登录,请登录后操作!"); Boolean preAuth = authConfig.getPreAuth();
return false; ArrayList<String> noAuthEndPoints = ListUtil.toList(authConfig.getNoAuthEndPoints());
ArrayList<String> needAuthEndPoints = ListUtil.toList(authConfig.getNeedAuthEndPoints());
if (StrUtil.isBlank(requestTokenHeader)) {
log.warn("Authorization token 为空");
} }
Object loginStatus = redisCache.getCacheObject(token);
// preAuth = false则所有请求除需要权限校验url集合needAuthEndPoints外都不需要身份认证
if (BooleanUtil.isFalse(preAuth)) {
Boolean contains = needAuthEndPoints.contains(requestURI);
// 必须登录的接口 && token为空
if (contains && StrUtil.isBlank(requestTokenHeader)) {
throw new BusinessException(ErrorCode.AUTH_ERROR, "尚未授权登录");
}
}else {
// preAuth = true;
// 配置文件无需登录的接口
Boolean contains = noAuthEndPoints.contains(requestURI);
// 具备排除标志的接口
Boolean excludeFlag = Boolean.FALSE;
for (String exclude : needAuthEndPoints) {
if (requestURI.contains(exclude)) {
excludeFlag = Boolean.TRUE;
break;
}
}
if (!contains && !excludeFlag && StrUtil.isBlank(requestTokenHeader)) {
throw new BusinessException(ErrorCode.AUTH_ERROR, "尚未授权登录");
}
}
if (StrUtil.isNotBlank(requestTokenHeader)){
Object loginStatus = redisCache.getCacheObject(requestTokenHeader);
if( Objects.isNull(loginStatus)){ if( Objects.isNull(loginStatus)){
response.getWriter().print("登陆异常,请查看!"); throw new BusinessException(ErrorCode.AUTH_ERROR, "登陆已过期");
return false;
} }
}
return true; return true;
} }

View File

@ -15,5 +15,16 @@ import com.jwl.driver.server.vo.LoginUserVo;
*/ */
public interface ITdSysUserService extends IService<TdSysUser> { public interface ITdSysUserService extends IService<TdSysUser> {
/**
*
* @param loginUserDto
* @return
*/
LoginUserVo login(LoginUserDto loginUserDto); LoginUserVo login(LoginUserDto loginUserDto);
/**
*
* @return
*/
Boolean loginOut();
} }

View File

@ -1,17 +1,22 @@
package com.jwl.driver.server.service.impl; package com.jwl.driver.server.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jwl.driver.server.dto.LoginUserDto; import com.jwl.driver.server.dto.LoginUserDto;
import com.jwl.driver.server.entity.TdSysUser; import com.jwl.driver.server.entity.TdSysUser;
import com.jwl.driver.server.exception.BusinessException;
import com.jwl.driver.server.mapper.TdSysUserMapper; import com.jwl.driver.server.mapper.TdSysUserMapper;
import com.jwl.driver.server.redis.RedisCache; import com.jwl.driver.server.redis.RedisCache;
import com.jwl.driver.server.service.ITdSysUserService; import com.jwl.driver.server.service.ITdSysUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jwl.driver.server.util.TokenThreadUtil;
import com.jwl.driver.server.vo.LoginUserVo; import com.jwl.driver.server.vo.LoginUserVo;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.UUID; import java.util.UUID;
/** /**
@ -29,13 +34,24 @@ public class TdSysUserServiceImpl extends ServiceImpl<TdSysUserMapper, TdSysUser
private RedisCache redisCache; private RedisCache redisCache;
@Override @Override
@Transactional(rollbackFor = Exception.class)
public LoginUserVo login(LoginUserDto loginUserDto) { public LoginUserVo login(LoginUserDto loginUserDto) {
//XI //todo 这里还需要校验验证码
LambdaQueryWrapper<TdSysUser> cond = new LambdaQueryWrapper<TdSysUser>() LambdaQueryWrapper<TdSysUser> cond = new LambdaQueryWrapper<TdSysUser>()
.eq(TdSysUser::getPhone,"18255439337"); .eq(TdSysUser::getPhone,"18255439337");
//用户不存在则直接注册登陆
TdSysUser tdSysUser = this.baseMapper.selectOne(cond); TdSysUser tdSysUser = this.baseMapper.selectOne(cond);
if (tdSysUser == null){ if (tdSysUser == null){
//创建用户 tdSysUser = new TdSysUser()
.setUserName("车友")
.setAvatar("")
.setPhone(loginUserDto.getPhone())
.setCreateTime(LocalDateTime.now());
int insert = this.getBaseMapper().insert(tdSysUser);
if (insert != 1){
throw new BusinessException("用户注册异常");
}
} }
String token = UUID.randomUUID().toString(); String token = UUID.randomUUID().toString();
@ -45,8 +61,14 @@ public class TdSysUserServiceImpl extends ServiceImpl<TdSysUserMapper, TdSysUser
loginUserVo.setToken(token); loginUserVo.setToken(token);
return loginUserVo; return loginUserVo;
}
@Override
public Boolean loginOut() {
String token = TokenThreadUtil.getToken();
if (StrUtil.isNotBlank(token)){
redisCache.deleteObject(token);
}
return Boolean.TRUE;
} }
} }

View File

@ -0,0 +1,65 @@
package com.jwl.driver.server.util;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.jwl.driver.server.constant.ErrorCode;
import com.jwl.driver.server.dto.SecurityUser;
import com.jwl.driver.server.entity.TdSysUser;
import com.jwl.driver.server.exception.BusinessException;
import com.jwl.driver.server.redis.RedisCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
*
*/
public class SecurityUtil {
private static final Logger log = LoggerFactory.getLogger(SecurityUtil.class);
private static final RedisCache redisCache = SpringAsyncUtil.<RedisCache>getBean(RedisCache.class);
/**
*
* @return
*/
public static SecurityUser getLoginUser() {
String token = TokenThreadUtil.getToken();
if (StrUtil.isBlank(token))
throw new BusinessException(ErrorCode.AUTH_ERROR, "尚未登录");
SecurityUser securityUser = null;
TdSysUser tdSysUser = redisCache.getCacheObject(token);
if (Objects.isNull(securityUser)){
throw new BusinessException(ErrorCode.AUTH_ERROR, "登录信息已失效");
}
BeanUtils.copyProperties(tdSysUser,securityUser);
securityUser.setToken(token);
return securityUser;
}
/**
*
* @return
*/
public static Long getUserId() {
Long userId = null;
SecurityUser loginUser = SecurityUtil.getLoginUser();
if (null != loginUser) {
userId = loginUser.getUserId();
}
return userId;
}
}

View File

@ -0,0 +1,62 @@
package com.jwl.driver.server.util;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public final class SpringAsyncUtil implements BeanFactoryPostProcessor, ApplicationContextAware {
private static ConfigurableListableBeanFactory beanFactory;
private static ApplicationContext applicationContext;
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
SpringAsyncUtil.beanFactory = beanFactory;
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringAsyncUtil.applicationContext = applicationContext;
}
public static <T> T getBean(String name) throws BeansException {
return (T)beanFactory.getBean(name);
}
public static <T> T getBean(Class<T> clz) throws BeansException {
T result = (T)beanFactory.getBean(clz);
return result;
}
public static boolean containsBean(String name) {
return beanFactory.containsBean(name);
}
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
return beanFactory.isSingleton(name);
}
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
return beanFactory.getType(name);
}
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
return beanFactory.getAliases(name);
}
public static <T> T getAopProxy(T invoker) {
return (T)AopContext.currentProxy();
}
public static String[] getActiveProfiles() {
return applicationContext.getEnvironment().getActiveProfiles();
}
public static String getActiveProfile() {
String[] activeProfiles = getActiveProfiles();
return (activeProfiles.length > 0) ? activeProfiles[0] : null;
}
}

View File

@ -0,0 +1,23 @@
package com.jwl.driver.server.util;
import cn.hutool.core.util.StrUtil;
/**
* 线-token
*/
public class TokenThreadUtil {
private static ThreadLocal<String> threadLocal = new ThreadLocal<>();
public static void setToken(String token) {
if (StrUtil.isNotBlank(token))
threadLocal.set(token);
}
public static String getToken() {
return threadLocal.get();
}
public static void remove() {
threadLocal.remove();
}
}

View File

@ -1,7 +1,7 @@
server: server:
port: 8888 port: 8888
# servlet: servlet:
# context-path: '/driver-api' context-path: '/driver-api'
spring: spring:
application: application:
@ -29,3 +29,18 @@ pagehelper:
knife4j: knife4j:
# 是否开启增强模式 # 是否开启增强模式
enable: true enable: true
# 是否需要校验token
driver:
auth-config:
# 约定为若 preAuth 为 true则所有请求除不需权限校验url集合noAuthEndPoints外都需要身份认证
# 为 false则所有请求除需要权限校验url集合needAuthEndPoints外都不需要身份认证
preAuth: true
# 不需权限校验url集合
noAuthEndPoints:
- /driver-api/v2/api-docs
- /driver-api/swagger-resources
- /driver-api/favicon.ico
# 需要权限校验url集合
needAuthEndPoints: