微服务改造
This commit is contained in:
@@ -1,24 +1,24 @@
|
||||
package com.ai.da;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
@Slf4j
|
||||
@SpringBootApplication
|
||||
@EnableScheduling
|
||||
@EnableAsync
|
||||
@EnableFeignClients
|
||||
@EnableDiscoveryClient
|
||||
public class AiDaApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(AiDaApplication.class, args);
|
||||
log.info("AiDaApplication 启动完成!");
|
||||
}
|
||||
|
||||
}
|
||||
package com.ai.da;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
@Slf4j
|
||||
@SpringBootApplication
|
||||
@EnableScheduling
|
||||
@EnableAsync
|
||||
@EnableFeignClients
|
||||
@EnableDiscoveryClient
|
||||
public class AiDaApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(AiDaApplication.class, args);
|
||||
log.info("AiDaApplication 启动完成!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package com.ai.da.common.config;
|
||||
|
||||
|
||||
import com.ai.da.common.interceptor.UserContextInterceptor;
|
||||
import org.hibernate.validator.HibernateValidator;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Validation;
|
||||
import jakarta.validation.Validator;
|
||||
import jakarta.validation.ValidatorFactory;
|
||||
@@ -17,11 +20,20 @@ public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
static final String ORIGINS[] = new String[]{"GET", "POST", "PUT", "DELETE"};
|
||||
|
||||
@Resource
|
||||
private UserContextInterceptor userContextInterceptor;
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**").allowedOriginPatterns("*").allowCredentials(true).allowedMethods(ORIGINS).maxAge(3600);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(userContextInterceptor)
|
||||
.addPathPatterns("/**");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Validator validator() {
|
||||
ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
package com.ai.da.common.config.exception;
|
||||
|
||||
public class TokenMissingOrExpiredException extends RuntimeException {
|
||||
public TokenMissingOrExpiredException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Throwable fillInStackTrace() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.ai.da.common.constant;
|
||||
|
||||
/**
|
||||
* @author yanglei
|
||||
* 异常类常量
|
||||
*/
|
||||
public class TokenConstant {
|
||||
/**
|
||||
* 固定session
|
||||
*/
|
||||
public static final String FIX_SESSION = "qrLS_003af9d8c1363fc4_6c97e932665c4460a1fdbfbf47ce3490";
|
||||
|
||||
public static final String PERMISSIONS = "9672233956";
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package com.ai.da.common.httpdata.token;
|
||||
|
||||
public enum TokenApis {
|
||||
/**
|
||||
* token
|
||||
*/
|
||||
GET_TOKEN("POST", "/api/openApi/v2/Weixin/QrCodeLoginCheck?session="),
|
||||
GENERATE_USER("POST", "/api/openApi/v2/Welink/TopicGetjson");
|
||||
|
||||
private String method;
|
||||
private String url;
|
||||
|
||||
TokenApis(String method, String url) {
|
||||
this.method = method;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public void setMethod(String method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package com.ai.da.common.httpdata.token;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
public class TokenQuery {
|
||||
|
||||
private static final String GET_TOKEN_DOMAIN = "https://www.szsige.com";
|
||||
private static final String GENERATE_USER_DOMAIN = "https://www.szsige.com";
|
||||
|
||||
public static JSONObject getToken(String session) {
|
||||
String url = GET_TOKEN_DOMAIN + TokenApis.GET_TOKEN.getUrl() + session;
|
||||
log.info("获取用户token接口请求url:" + url);
|
||||
HttpResponse httpResponse = HttpUtil.createPost(url).execute();
|
||||
log.info("获取用户token接口响应:" + httpResponse);
|
||||
if (httpResponse.isOk() && StrUtil.isNotEmpty(httpResponse.body())) {
|
||||
return JSONObject.parseObject(httpResponse.body());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static JSONObject generateUser(Map<String, Object> param, String token) {
|
||||
HttpResponse httpResponse = HttpUtil.createPost(GENERATE_USER_DOMAIN + TokenApis.GENERATE_USER.getUrl())
|
||||
.body(JSONObject.toJSONString(param != null ? param : new HashMap<>()))
|
||||
.header("Authorization", "Bearer " + token)
|
||||
.header("X-Promiss", "9672233956")
|
||||
.execute();
|
||||
log.info("生成用户信息接口响应:" + httpResponse);
|
||||
if (httpResponse.isOk() && StrUtil.isNotEmpty(httpResponse.body())) {
|
||||
return JSONObject.parseObject(httpResponse.body());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package com.ai.da.common.security;
|
||||
|
||||
import com.ai.da.common.response.Response;
|
||||
import com.ai.da.common.response.ResultEnum;
|
||||
import com.ai.da.common.utils.JSONResponseUtils;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @ClassName UserAuthAccessDeniedHandler
|
||||
* @Description 无权限处理类
|
||||
* @Author dwjian
|
||||
* @Date 2020/7/9 20:30
|
||||
*/
|
||||
@Component
|
||||
public class UserAuthAccessDeniedHandler implements AccessDeniedHandler {
|
||||
@Override
|
||||
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException exception) throws IOException {
|
||||
Response<String> response = Response.error(ResultEnum.NO_PERMISSION.getCode(), ResultEnum.NO_PERMISSION.getMsg());
|
||||
JSONResponseUtils.build(httpServletResponse, response);
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package com.ai.da.common.security;
|
||||
|
||||
import com.ai.da.common.response.Response;
|
||||
import com.ai.da.common.response.ResultEnum;
|
||||
import com.ai.da.common.utils.JSONResponseUtils;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @ClassName UserAuthenticationEntryPointHandler
|
||||
* @Description 未登录处理类
|
||||
* @Author dwjian
|
||||
* @Date 2020/7/9 20:13
|
||||
*/
|
||||
@Component
|
||||
public class UserAuthenticationEntryPointHandler implements AuthenticationEntryPoint {
|
||||
@Override
|
||||
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
|
||||
Response<String> response = Response.error(ResultEnum.NO_LOGIN.getCode(), ResultEnum.NO_LOGIN.getMsg());
|
||||
httpServletResponse.setStatus(401);
|
||||
JSONResponseUtils.build(httpServletResponse, response);
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package com.ai.da.common.security;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
/**
|
||||
* @author: dangweijian
|
||||
* @description: 认证管理器
|
||||
* @create: 2020-07-10 15:58
|
||||
**/
|
||||
@Component
|
||||
public class UserAuthenticationManager implements AuthenticationManager {
|
||||
|
||||
@Resource
|
||||
private UserAuthenticationProvider userAuthenticationProvider;
|
||||
|
||||
@Override
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
return userAuthenticationProvider.authenticate(authentication);
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package com.ai.da.common.security;
|
||||
|
||||
import com.ai.da.common.config.RsaProperties;
|
||||
import com.ai.da.common.utils.RsaDecryptUtils;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author: dangweijian
|
||||
* @description: 登录校验处理类
|
||||
* @create: 2020-07-09 14:39
|
||||
**/
|
||||
@Component
|
||||
public class UserAuthenticationProvider implements AuthenticationProvider {
|
||||
|
||||
@Override
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
String userName = (String) authentication.getPrincipal();
|
||||
String password = (String) authentication.getCredentials();
|
||||
try {
|
||||
password = RsaDecryptUtils.decrypt(password, RsaProperties.privateKey);
|
||||
} catch (Exception e) {
|
||||
throw new BadCredentialsException("用户名或密码错误");
|
||||
}
|
||||
// User user = userService.getByUsername(userName);
|
||||
// if (user == null) {
|
||||
// throw new UsernameNotFoundException("用户名或密码错误");
|
||||
// }
|
||||
// //账号已冻结
|
||||
// if(user.getStatus() == 1){
|
||||
// throw new LockedException("账号已冻结");
|
||||
// }
|
||||
// if(!passwordEncoder.matches(password, user.getPassword())){
|
||||
// throw new BadCredentialsException("用户名或密码错误");
|
||||
// }
|
||||
// //超级管理员
|
||||
// Set<SimpleGrantedAuthority> authorities = new HashSet<>();
|
||||
// if(user.getIsAdmin()) {
|
||||
// authorities.add(new SimpleGrantedAuthority("admin"));
|
||||
// return new UsernamePasswordAuthenticationToken(user, password, authorities);
|
||||
// }else {
|
||||
// List<RoleMenuDto> userMenus = menuService.getRoleMenusByUserId(user.getId(), null);
|
||||
// if(CollUtil.isNotEmpty(userMenus)){
|
||||
// authorities.addAll(userMenus.stream().map(RoleMenuDto::getPermission).filter(StringUtils::isNotEmpty).map(SimpleGrantedAuthority::new).collect(Collectors.toSet()));
|
||||
// }
|
||||
// return new UsernamePasswordAuthenticationToken(user, password, authorities);
|
||||
// }
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> aClass) {
|
||||
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(aClass);
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package com.ai.da.common.security;
|
||||
|
||||
import com.ai.da.common.response.Response;
|
||||
import com.ai.da.common.response.ResultEnum;
|
||||
import com.ai.da.common.utils.JSONResponseUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.authentication.*;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @ClassName UserLoginFailureHandler
|
||||
* @Description 登录失败处理类
|
||||
* @Author dwjian
|
||||
* @Date 2020/7/9 20:17
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class UserLoginFailureHandler implements AuthenticationFailureHandler {
|
||||
@Override
|
||||
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
|
||||
Response<String> response;
|
||||
if (e instanceof UsernameNotFoundException || e instanceof BadCredentialsException) {
|
||||
response = Response.fail(e.getMessage());
|
||||
} else if (e instanceof LockedException) {
|
||||
response = Response.fail(ResultEnum.ACCOUNT_LOCK);
|
||||
} else if (e instanceof CredentialsExpiredException) {
|
||||
response = Response.fail("证书过期,请联系管理员!");
|
||||
} else if (e instanceof AccountExpiredException) {
|
||||
response = Response.fail("账户过期,请联系管理员!");
|
||||
} else if (e instanceof DisabledException) {
|
||||
response = Response.fail("账户被禁用,请联系管理员!");
|
||||
} else if (e instanceof AuthenticationServiceException) {
|
||||
response = Response.fail(e.getMessage());
|
||||
} else {
|
||||
log.error("登录失败:", e);
|
||||
response = Response.fail("登录失败!");
|
||||
}
|
||||
JSONResponseUtils.build(httpServletResponse, response);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package com.ai.da.common.security;
|
||||
|
||||
import com.ai.da.common.response.ResultEnum;
|
||||
import com.ai.da.common.utils.JSONResponseUtils;
|
||||
import com.ai.da.common.response.Response;
|
||||
import com.ai.da.common.security.jwt.JWTTokenHelper;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author: dangweijian
|
||||
* @description: 登录成功处理类
|
||||
* @create: 2020-07-09 14:58
|
||||
**/
|
||||
@Component
|
||||
public class UserLoginSuccessHandler implements AuthenticationSuccessHandler {
|
||||
|
||||
@Resource
|
||||
private JWTTokenHelper jwtTokenHelper;
|
||||
|
||||
@Override
|
||||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
|
||||
// User user = (User) authentication.getPrincipal();
|
||||
// AuthPrincipalVo principal = new AuthPrincipalVo();
|
||||
// BeanUtils.copyProperties(user, principal);
|
||||
// // 获取用户角色
|
||||
// List<UserRoleDto> userRoles = roleService.getUserRoles(user.getId(), 0);
|
||||
// principal.setRoles(userRoles);
|
||||
// // 获取角色部门
|
||||
// if(CollUtil.isNotEmpty(userRoles)){
|
||||
// principal.setDepts(deptService.getDeptByRoleIds(userRoles.stream().map(UserRoleDto::getRoleId).collect(Collectors.toList())));
|
||||
// }
|
||||
// // 用户角色权限
|
||||
// List<String> authorities = new ArrayList<>(authentication.getAuthorities()).stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
|
||||
// principal.setAuthorities(authorities);
|
||||
// AuthVo authVo = new AuthVo();
|
||||
// authVo.setAuthorities(authorities);
|
||||
// authVo.setToken(jwtTokenHelper.createToken(principal));
|
||||
// authVo.setPrincipal(principal);
|
||||
// user.setLastLoginTime(new Date());
|
||||
// userService.updateById(user);
|
||||
JSONResponseUtils.build(response, Response.success(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMsg(), null));
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.ai.da.common.security;
|
||||
|
||||
import org.springframework.security.access.PermissionEvaluator;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @ClassName UserPermissionEvaluator
|
||||
* @Description 权限校验处理器
|
||||
* @Author dwjian
|
||||
* @Date 2020/7/12 10:16
|
||||
*/
|
||||
@Component
|
||||
public class UserPermissionEvaluator implements PermissionEvaluator {
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(Authentication authentication, Object targetUrl, Object permission) {
|
||||
System.out.println(authentication);
|
||||
System.out.println(targetUrl);
|
||||
System.out.println(permission);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
|
||||
System.out.println(authentication);
|
||||
System.out.println(targetId);
|
||||
System.out.println(targetType);
|
||||
System.out.println(permission);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
package com.ai.da.common.security.config;
|
||||
|
||||
import com.ai.da.common.security.*;
|
||||
import com.ai.da.common.security.filter.AuthenticationFilter;
|
||||
import com.ai.da.common.security.filter.UserAuthenticationProcessingFilter;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableMethodSecurity(prePostEnabled = true)
|
||||
@EnableConfigurationProperties(SecurityProperties.class)
|
||||
public class SecurityConfig {
|
||||
|
||||
@Resource
|
||||
private SecurityProperties securityProperties;
|
||||
@Resource
|
||||
private UserLoginSuccessHandler userLoginSuccessHandler;
|
||||
@Resource
|
||||
private UserLoginFailureHandler userLoginFailureHandler;
|
||||
@Resource
|
||||
private UserAuthAccessDeniedHandler userAuthAccessDeniedHandler;
|
||||
@Resource
|
||||
private UserAuthenticationEntryPointHandler userAuthenticationEntryPointHandler;
|
||||
@Resource
|
||||
private UserAuthenticationManager userAuthenticationManager;
|
||||
@Resource
|
||||
private UserAuthenticationProcessingFilter userAuthenticationProcessingFilter;
|
||||
|
||||
/**
|
||||
* 不通过注入spring管理 让Security来管理 这样自定义的Filter就不会走,.permitAll()才能起作用
|
||||
*/
|
||||
@Resource
|
||||
private AuthenticationFilter authenticationFilter;
|
||||
@Resource
|
||||
private UserPermissionEvaluator userPermissionEvaluator;
|
||||
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManager() throws Exception {
|
||||
return this.userAuthenticationManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
|
||||
httpSecurity
|
||||
.cors(Customizer.withDefaults())
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers(
|
||||
new AntPathRequestMatcher("/doc.html"),
|
||||
new AntPathRequestMatcher("/swagger-ui.html"),
|
||||
new AntPathRequestMatcher("/swagger-ui/**"),
|
||||
new AntPathRequestMatcher("/swagger-resources/**"),
|
||||
new AntPathRequestMatcher("/v2/api-docs"),
|
||||
new AntPathRequestMatcher("/v3/api-docs/**"),
|
||||
new AntPathRequestMatcher("/webjars/**")
|
||||
).permitAll()
|
||||
.requestMatchers(securityProperties.getIgnorePaths()).permitAll()
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.headers(headers -> headers
|
||||
.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable)
|
||||
.cacheControl(cache -> cache.disable())
|
||||
)
|
||||
.exceptionHandling(exception -> exception
|
||||
.authenticationEntryPoint(userAuthenticationEntryPointHandler)
|
||||
.accessDeniedHandler(userAuthAccessDeniedHandler)
|
||||
)
|
||||
.formLogin(form -> form
|
||||
.loginProcessingUrl(securityProperties.getAuthApi())
|
||||
.successHandler(userLoginSuccessHandler)
|
||||
.failureHandler(userLoginFailureHandler)
|
||||
)
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
.sessionManagement(session -> session
|
||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||
);
|
||||
|
||||
//自定义过滤器在登录时认证用户名、密码
|
||||
httpSecurity.addFilterAt(userAuthenticationProcessingFilter, UsernamePasswordAuthenticationFilter.class)
|
||||
.addFilterBefore(authenticationFilter, BasicAuthenticationFilter.class);
|
||||
|
||||
return httpSecurity.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DefaultWebSecurityExpressionHandler userSecurityExpressionHandler() {
|
||||
DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
|
||||
handler.setPermissionEvaluator(userPermissionEvaluator);
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.ai.da.common.security.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* @author: dangweijian
|
||||
* @description: JWT配置类
|
||||
* @create: 2020-07-09 09:38
|
||||
**/
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "spring.security")
|
||||
public class SecurityProperties {
|
||||
|
||||
private String jwtSecret;
|
||||
|
||||
private String jwtTokenHeader;
|
||||
|
||||
private String jwtTokenPrefix;
|
||||
|
||||
private long jwtExpiration;
|
||||
|
||||
private String[] ignorePaths;
|
||||
|
||||
private String authApi;
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
package com.ai.da.common.security.filter;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.ai.da.common.config.exception.TokenMissingOrExpiredException;
|
||||
import com.ai.da.common.context.UserContext;
|
||||
import com.ai.da.common.security.config.SecurityProperties;
|
||||
import com.ai.da.common.security.jwt.JWTTokenHelper;
|
||||
import com.ai.da.common.utils.LocalCacheUtils;
|
||||
import com.ai.da.common.utils.RedisUtil;
|
||||
import com.ai.da.common.utils.MultiReadHttpServletRequest;
|
||||
import com.ai.da.common.utils.MultiReadHttpServletResponse;
|
||||
import com.ai.da.common.utils.RequestInfoUtil;
|
||||
import com.ai.da.model.vo.AuthPrincipalVo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.util.StopWatch;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: dangweijian
|
||||
* @description: 认证拦截器
|
||||
* @create: 2020-07-10 16:50
|
||||
**/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class AuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
@Resource
|
||||
private JWTTokenHelper jwtTokenHelper;
|
||||
@Resource
|
||||
private SecurityProperties properties;
|
||||
@Resource
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
private static final List<String> FILTER_URL =
|
||||
Arrays.asList("/favicon.ico", "/doc.html", "/swagger-ui.html",
|
||||
"/swagger-resources", "/swagger-resources/", "/swagger-resources/configuration/ui", "/swagger-resources/configuration/security",
|
||||
"/webjars/", "/v2/api-docs", "/v3/api-docs", "/v3/api-docs/swagger-config",
|
||||
"/api/account/login", "/api/account/preLogin", "api/account/sendEmail","api/account/noLoginRequired",
|
||||
"/api/account/resetPwd",
|
||||
"/api/python/saveGeneratePicture", "/api/python/getLibraryByUserId",
|
||||
"/api/third/party/addUser","/api/third/party/addTrialUser", "/api/third/party/editUser", "/api/element/initDefaultSysFile",
|
||||
"/api/third/party/addNoLoginRequiredNew","/api/third/party/deleteNoLoginRequiredNew","/api/third/party/updateNoLoginRequiredNew",
|
||||
"/api/third/party/existNoLoginRequired","/api/third/party/getRedirectUrl",
|
||||
"/api/python/flush","/api/account/healthy","/api/ali-pay/trade/notify","/api/paypal/ipn/back","/api/alipay-hk/trade/notify",
|
||||
"/api/portfolio/page", "/api/portfolio/detail", "/api/portfolio/commentPage", "/api/portfolio/viewsIncrease",
|
||||
"/api/account/designWorksRegister","/api/account/questionnaire","/api/stripe/trade/notify",
|
||||
"/notification","/api/account/activateNewEmail","/api/third/party/auth/google_callback","/api/third/party/parseGoogleCredential","/api/third/party/receiveDesignResults","/api/third/party/parseWeChatCode","/api/third/party/receiveDesignParams"
|
||||
, "/api/account/schoolLogin", "/api/account/enterpriseLogin", "/api/account/organizationNameSearch",
|
||||
"/api/llm/stream",
|
||||
//GlobalAwardController
|
||||
"/api/global-award"
|
||||
);
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest httpServletRequest, @NonNull HttpServletResponse httpServletResponse, @NonNull FilterChain filterChain) throws ServletException, IOException {
|
||||
String requestURI = httpServletRequest.getRequestURI();
|
||||
|
||||
if (calculateUrl(requestURI)/* || hasAuthorizationToken(httpServletRequest)*/) {
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
HttpServletRequest wrappedRequest = httpServletRequest;
|
||||
HttpServletResponse wrappedResponse = httpServletResponse;
|
||||
try {
|
||||
stopWatch.start();
|
||||
if ((httpServletRequest.getContentType() == null && httpServletRequest.getContentLength() > 0) || (httpServletRequest.getContentType() != null && !httpServletRequest.getContentType().contains("application/json"))) {
|
||||
extracted(wrappedRequest);
|
||||
filterChain.doFilter(wrappedRequest, wrappedResponse);
|
||||
} else {
|
||||
wrappedRequest = new MultiReadHttpServletRequest(httpServletRequest);
|
||||
wrappedResponse = new MultiReadHttpServletResponse(httpServletResponse);
|
||||
extracted(wrappedRequest);
|
||||
// excel导出使用原始response,不对响应做包装
|
||||
if (requestURI.equals("/api/account/exportAccountsToExcel")) {
|
||||
filterChain.doFilter(httpServletRequest, httpServletResponse); // 不包装
|
||||
} else {
|
||||
filterChain.doFilter(wrappedRequest, wrappedResponse);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
SecurityContextHolder.clearContext();
|
||||
throw e;
|
||||
} finally {
|
||||
stopWatch.stop();
|
||||
}
|
||||
} else {
|
||||
//先清空当前线程变量,防止上一个线程遗留
|
||||
UserContext.delete();
|
||||
filterChain.doFilter(httpServletRequest, httpServletResponse);
|
||||
}
|
||||
}
|
||||
|
||||
private Boolean calculateUrl(String requestURI) {
|
||||
String filterUrl = FILTER_URL.stream().filter(url -> requestURI.contains(url)).findFirst().orElse(null);
|
||||
return null == filterUrl ? Boolean.TRUE : Boolean.FALSE;
|
||||
}
|
||||
|
||||
private boolean hasAuthorizationToken(HttpServletRequest request) {
|
||||
String authorizationHeader = request.getHeader("Authorization");
|
||||
return authorizationHeader != null && authorizationHeader.startsWith("Bearer");
|
||||
}
|
||||
|
||||
private void extracted(HttpServletRequest request) {
|
||||
String jwtToken = request.getHeader(properties.getJwtTokenHeader());
|
||||
// log.debug("后台检查令牌:{}", jwtToken);
|
||||
|
||||
if (StrUtil.isBlank(jwtToken)) {
|
||||
String ipAddress = RequestInfoUtil.getIpAddress(request);
|
||||
log.info("本次请求的ip为 : " + ipAddress);
|
||||
// throw new RuntimeException("请传入token!");
|
||||
throw new TokenMissingOrExpiredException("请传入token!");
|
||||
}
|
||||
if(jwtToken.equals("Bearer-eyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiIyIiwic3ViIjoie1wiaWRcIjoyLFwidXNlcm5hbWVcIjpcImxpcnNcIn0iLCJpYXQiOjE2NjU3NDEwODcsImlzcyI6IkRXSiIsImF1dGhvcml0aWVzIjoiW10iLCJleHAiOjE2NzQzODEwODd9.ShM9R_NNFD7oo1OvxrEgg7PFeWinOuAKkuInUCMQupp66s64Hhv8tN0Wwr83nIN4rHPqtn95wmd4msWcvaFYJA")){
|
||||
//写死 暂时放行
|
||||
return;
|
||||
}
|
||||
// 检查token
|
||||
boolean validate = jwtTokenHelper.validateToken(jwtToken);
|
||||
if (validate) {
|
||||
AuthPrincipalVo principal = jwtTokenHelper.parserToUser(jwtToken);
|
||||
if (principal == null) {
|
||||
// throw new RuntimeException("TOKEN已过期,请重新登录!");
|
||||
throw new TokenMissingOrExpiredException("TOKEN已过期,请重新登录!(token without userInfo)");
|
||||
}
|
||||
//先清空当前线程变量,防止上一个线程遗留
|
||||
UserContext.delete();
|
||||
//存取用户信息到缓存
|
||||
UserContext.setUserHolder(principal);
|
||||
// 校验 token:先查本地缓存,再查 Redis,保证服务重启后仍然有效
|
||||
String userIdStr = String.valueOf(principal.getId());
|
||||
String cacheToken = LocalCacheUtils.getTokenCache(userIdStr);
|
||||
|
||||
if (StringUtils.isEmpty(cacheToken)) {
|
||||
// 本地缓存为空时,尝试从 Redis 读取
|
||||
cacheToken = redisUtil.getLoginToken(principal.getId());
|
||||
if (StringUtils.isEmpty(cacheToken)) {
|
||||
// throw new RuntimeException("TOKEN已过期,请重新登录!");
|
||||
throw new TokenMissingOrExpiredException("TOKEN已过期,请重新登录!(cache & redis empty)");
|
||||
}
|
||||
// 将 Redis 中的 token 回填到本地缓存,减少后续 Redis 访问
|
||||
LocalCacheUtils.setTokenCache(userIdStr, cacheToken);
|
||||
}
|
||||
if(!cacheToken.equals(jwtToken) ){
|
||||
// throw new RuntimeException("TOKEN已过期,请重新登录!");
|
||||
throw new TokenMissingOrExpiredException("TOKEN已过期,请重新登录!(token not match local cache)");
|
||||
}
|
||||
// UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(null, null);
|
||||
// SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package com.ai.da.common.security.filter;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.ai.da.common.security.UserLoginSuccessHandler;
|
||||
import com.ai.da.common.security.config.SecurityProperties;
|
||||
import com.ai.da.common.utils.RedisCacheUtils;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.ai.da.common.security.UserAuthenticationManager;
|
||||
import com.ai.da.common.security.UserLoginFailureHandler;
|
||||
import com.ai.da.common.utils.MultiReadHttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* @author: dangweijian
|
||||
* @description: 用户认证过滤器
|
||||
* @create: 2020-07-10 15:58
|
||||
**/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class UserAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {
|
||||
|
||||
/**
|
||||
* @param securityProperties 配置(从配置中读取登录url)
|
||||
* @param authenticationManager 认证管理器
|
||||
* @param adminAuthenticationSuccessHandler 认证成功处理器
|
||||
* @param adminAuthenticationFailureHandler 认证失败处理器
|
||||
*/
|
||||
public UserAuthenticationProcessingFilter(SecurityProperties securityProperties, UserAuthenticationManager authenticationManager, UserLoginSuccessHandler adminAuthenticationSuccessHandler, UserLoginFailureHandler adminAuthenticationFailureHandler) {
|
||||
super(new AntPathRequestMatcher(securityProperties.getAuthApi(), HttpMethod.POST.name()));
|
||||
this.setAuthenticationManager(authenticationManager);
|
||||
this.setAuthenticationSuccessHandler(adminAuthenticationSuccessHandler);
|
||||
this.setAuthenticationFailureHandler(adminAuthenticationFailureHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
|
||||
if (request.getContentType() == null || !request.getContentType().contains("application/json")) {
|
||||
throw new AuthenticationServiceException("请求头类型不支持: " + request.getContentType());
|
||||
}
|
||||
UsernamePasswordAuthenticationToken authRequest;
|
||||
try {
|
||||
MultiReadHttpServletRequest wrappedRequest = new MultiReadHttpServletRequest(request);
|
||||
// 将前端传递的数据转换成jsonBean数据格式
|
||||
JSONObject jsonObject = JSONObject.parseObject(wrappedRequest.getBodyJsonStrByJson(wrappedRequest));
|
||||
String code = jsonObject.getString("code");
|
||||
String uuid = jsonObject.getString("uuid");
|
||||
if (StrUtil.isEmpty(code) || StrUtil.isEmpty(uuid) || !code.equals(RedisCacheUtils.get("code-key-" + uuid, String.class))) {
|
||||
throw new AuthenticationServiceException("验证码错误");
|
||||
}
|
||||
RedisCacheUtils.delete("code-key-" + uuid);
|
||||
authRequest = new UsernamePasswordAuthenticationToken(jsonObject.get("username"), jsonObject.get("password"), null);
|
||||
authRequest.setDetails(authenticationDetailsSource.buildDetails(wrappedRequest));
|
||||
} catch (Exception e) {
|
||||
throw new AuthenticationServiceException(e.getMessage());
|
||||
}
|
||||
return this.getAuthenticationManager().authenticate(authRequest);
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
package com.ai.da.common.security.jwt;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.digest.DigestUtil;
|
||||
import com.ai.da.common.constant.CommonConstant;
|
||||
import com.ai.da.common.security.config.SecurityProperties;
|
||||
import com.ai.da.model.vo.AuthPrincipalVo;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import javax.crypto.SecretKey;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author: dangweijian
|
||||
* @description: JWT工具
|
||||
* @create: 2020-07-09 09:27
|
||||
**/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class JWTTokenHelper {
|
||||
|
||||
@Resource
|
||||
private SecurityProperties securityProperties;
|
||||
|
||||
private static final String ISSUER = "DWJ";
|
||||
private static final String AUTHORITIES = "authorities";
|
||||
private static final String CHANGE_MAILBOX = "changeMailbox";
|
||||
|
||||
public String createToken(AuthPrincipalVo principal) {
|
||||
SecretKey key = buildSigningKey();
|
||||
String token = Jwts.builder()
|
||||
.id(String.valueOf(principal.getId()))
|
||||
.subject(JSONObject.toJSONString(principal))
|
||||
.issuedAt(new Date())
|
||||
.issuer(ISSUER)
|
||||
.claim(AUTHORITIES, JSON.toJSONString(new ArrayList<>()))//自定义属性 权限
|
||||
.expiration(new Date(System.currentTimeMillis() + securityProperties.getJwtExpiration()))
|
||||
.signWith(key)
|
||||
.compact();
|
||||
token = securityProperties.getJwtTokenPrefix() + token;
|
||||
return token;
|
||||
}
|
||||
|
||||
public boolean validateToken(String token) {
|
||||
Claims claims = parser(token);
|
||||
if (MapUtil.isEmpty(claims)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public AuthPrincipalVo parserToUser(String token) {
|
||||
String subject = parser(token).getSubject();
|
||||
if (StrUtil.isNotEmpty(subject)) {
|
||||
return JSONObject.parseObject(subject, AuthPrincipalVo.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Claims parser(String token) {
|
||||
token = token.replaceAll(securityProperties.getJwtTokenPrefix(), "");
|
||||
SecretKey key = buildSigningKey();
|
||||
return Jwts.parser()
|
||||
.verifyWith(key)
|
||||
.build()
|
||||
.parseSignedClaims(token)
|
||||
.getPayload();
|
||||
}
|
||||
|
||||
public String createToken(Long userId, String userEmail){
|
||||
SecretKey key = buildSigningKey();
|
||||
String token = Jwts.builder()
|
||||
.id(String.valueOf(userId))
|
||||
.subject(userEmail + "_" + userId)
|
||||
.issuedAt(new Date())
|
||||
.issuer(ISSUER)
|
||||
.claim(CHANGE_MAILBOX, JSON.toJSONString(new ArrayList<>()))//自定义属性 权限
|
||||
.expiration(new Date(System.currentTimeMillis() + CommonConstant.CHANGE_MAILBOX_LINK_VALIDITY))
|
||||
.signWith(key)
|
||||
.compact();
|
||||
return token;
|
||||
}
|
||||
|
||||
public String parseToEmailAndId(String token) {
|
||||
return parser(token).getSubject();
|
||||
}
|
||||
|
||||
/**
|
||||
* JWT 要求 HMAC-SHA 的密钥至少 256 bit,这里统一扩展/哈希密钥长度避免 WeakKeyException。
|
||||
*/
|
||||
private SecretKey buildSigningKey() {
|
||||
byte[] raw = securityProperties.getJwtSecret().getBytes(StandardCharsets.UTF_8);
|
||||
if (raw.length < 32) {
|
||||
raw = DigestUtil.sha256(raw);
|
||||
}
|
||||
return Keys.hmacShaKeyFor(raw);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package com.ai.da.common.utils;
|
||||
|
||||
import com.ai.da.model.vo.AuthPrincipalVo;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
public class SecurityContextUtils {
|
||||
|
||||
public static AuthPrincipalVo getCurrentUser() {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (authentication != null && authentication.getPrincipal() != null) {
|
||||
return (AuthPrincipalVo) authentication.getPrincipal();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Long getCurrentUserId() {
|
||||
AuthPrincipalVo currentUser = getCurrentUser();
|
||||
if (currentUser != null) {
|
||||
return currentUser.getId();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getCurrentUsername() {
|
||||
AuthPrincipalVo currentUser = getCurrentUser();
|
||||
if (currentUser != null) {
|
||||
return currentUser.getUsername();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,8 @@ import com.ai.da.common.enums.LoginTypeEnum;
|
||||
import com.ai.da.common.enums.ProductEnum;
|
||||
import com.ai.da.common.response.PageBaseResponse;
|
||||
import com.ai.da.common.response.ResultEnum;
|
||||
import com.ai.da.common.security.jwt.JWTTokenHelper;
|
||||
import com.ai.da.common.utils.TokenGenerateUtils;
|
||||
import com.ai.da.feign.gateway.GatewayFeignClient;
|
||||
import com.ai.da.feign.seller.SellerFeignClient;
|
||||
import com.ai.da.common.utils.*;
|
||||
import com.ai.da.mapper.primary.*;
|
||||
@@ -95,11 +96,14 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
private AccountExtendMapper accountExtendMapper;
|
||||
|
||||
@Resource
|
||||
private JWTTokenHelper jwtTokenHelper;
|
||||
private TokenGenerateUtils tokenGenerateUtils;
|
||||
|
||||
@Resource
|
||||
private SellerFeignClient sellerFeignClient;
|
||||
|
||||
@Resource
|
||||
private GatewayFeignClient gatewayFeignClient;
|
||||
|
||||
@Resource
|
||||
private AccountLoginLogService accountLoginLogService;
|
||||
|
||||
@@ -140,9 +144,6 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
@Resource
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
@Resource
|
||||
private com.ai.da.common.security.config.SecurityProperties securityProperties;
|
||||
|
||||
@Resource
|
||||
private UserFollowService userFollowService;
|
||||
|
||||
@@ -357,11 +358,11 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
principal.setUsername(account.getUserName());
|
||||
principal.setLanguage(account.getLanguage());
|
||||
principal.setCountry(account.getCountry());
|
||||
String token2 = jwtTokenHelper.createToken(principal);
|
||||
String token2 = tokenGenerateUtils.createToken(principal);
|
||||
// 本地 JVM 缓存(适配旧逻辑)
|
||||
LocalCacheUtils.setTokenCache(String.valueOf(account.getId()), token2);
|
||||
// 同步写入 Redis,重启后仍然可用
|
||||
long jwtExpiration = securityProperties.getJwtExpiration();
|
||||
long jwtExpiration = tokenGenerateUtils.getJwtExpiration();
|
||||
redisUtil.setLoginToken(account.getId(), token2, jwtExpiration);
|
||||
return token2;
|
||||
}
|
||||
@@ -618,12 +619,18 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
|
||||
@Override
|
||||
public Boolean logout(AccountLogoutDTO accountLogoutDTO) {
|
||||
// jwt 本身失效比较难做,统一用缓存实现:删除缓存即失效
|
||||
// 1. 删除本地缓存(保留,防止 Gateway 未启动时还能本地验证)
|
||||
String userIdStr = String.valueOf(accountLogoutDTO.getUserId());
|
||||
LocalCacheUtils.delTokenCache(userIdStr);
|
||||
// 同时删除 Redis 中的 token,防止服务重启后仍然有效
|
||||
// 2. 删除 Redis 中的 token(Gateway 黑名单会接力生效)
|
||||
redisUtil.deleteLoginToken(accountLogoutDTO.getUserId());
|
||||
// 同步调用 seller 清除本地缓存
|
||||
// 3. 调用 Gateway 黑名单接口,将 token 加入 Redis 黑名单
|
||||
try {
|
||||
gatewayFeignClient.logout(accountLogoutDTO.getUserId());
|
||||
} catch (Exception e) {
|
||||
log.warn("调用 Gateway 黑名单接口失败,userId={}, error={}", accountLogoutDTO.getUserId(), e.getMessage());
|
||||
}
|
||||
// 4. 同步调用 seller 清除本地缓存(兼容未接入 Gateway 的节点)
|
||||
try {
|
||||
sellerFeignClient.clearTokenCache(accountLogoutDTO.getUserId());
|
||||
} catch (Exception e) {
|
||||
@@ -2163,7 +2170,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
redisUtil.addToString(key, newMailbox, CommonConstant.CHANGE_MAILBOX_LINK_VALIDITY / 1000);
|
||||
|
||||
String username = userHolder.getUsername();
|
||||
String token = jwtTokenHelper.createToken(accountId, newMailbox);
|
||||
String token = tokenGenerateUtils.createMailboxToken(accountId, newMailbox);
|
||||
// 准备激活链接,链接应该要有有效期
|
||||
String link = "?" + token;
|
||||
// 向新邮箱发送邮件,邮件附带激活链接,点击链接进行验证
|
||||
@@ -2173,7 +2180,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
// 验证激活链接
|
||||
public void activateNewEmail(String token){
|
||||
// 获取链接地址信息,更新指定用户邮箱
|
||||
String emailAndId = jwtTokenHelper.parseToEmailAndId(token);
|
||||
String emailAndId = tokenGenerateUtils.parseMailboxToken(token);
|
||||
String newMailbox = emailAndId.substring(0, emailAndId.lastIndexOf("_"));
|
||||
String accountId = emailAndId.substring(emailAndId.lastIndexOf("_") + 1);
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import com.ai.da.common.enums.CollectionLevel1TypeEnum;
|
||||
import com.ai.da.common.response.PageBaseResponse;
|
||||
import com.ai.da.common.response.PageResponse;
|
||||
import com.ai.da.common.response.Response;
|
||||
import com.ai.da.common.security.jwt.JWTTokenHelper;
|
||||
import com.ai.da.common.utils.TokenGenerateUtils;
|
||||
import com.ai.da.common.utils.MinioUtil;
|
||||
import com.ai.da.mapper.primary.*;
|
||||
import com.ai.da.mapper.primary.entity.*;
|
||||
@@ -70,7 +70,7 @@ public class LLMServiceImpl implements LLMService {
|
||||
@Resource
|
||||
private WorkspaceRelStyleMapper workspaceRelStyleMapper;
|
||||
@Resource
|
||||
private JWTTokenHelper jwtTokenHelper;
|
||||
private TokenGenerateUtils tokenGenerateUtils;
|
||||
@Resource
|
||||
private DesignService designService;
|
||||
private final ExecutorService executor = Executors.newCachedThreadPool();
|
||||
@@ -89,9 +89,9 @@ public class LLMServiceImpl implements LLMService {
|
||||
|
||||
executor.submit(() -> {
|
||||
try {
|
||||
boolean validate = jwtTokenHelper.validateToken(token); //
|
||||
boolean validate = tokenGenerateUtils.validateToken(token); //
|
||||
if (validate) {
|
||||
AuthPrincipalVo principal = jwtTokenHelper.parserToUser(token);
|
||||
AuthPrincipalVo principal = tokenGenerateUtils.parserToUser(token);
|
||||
Long accountId = principal.getId();
|
||||
// String url = "http://18.167.251.121:10002/chat-stream";
|
||||
String url = "http://10.1.1.240:1013/chat-stream";
|
||||
@@ -237,10 +237,10 @@ public class LLMServiceImpl implements LLMService {
|
||||
|
||||
executor.submit(() -> {
|
||||
try {
|
||||
boolean validate = jwtTokenHelper.validateToken(token);
|
||||
boolean validate = tokenGenerateUtils.validateToken(token);
|
||||
// boolean validate = true;
|
||||
if (validate) {
|
||||
AuthPrincipalVo principal = jwtTokenHelper.parserToUser(token);
|
||||
AuthPrincipalVo principal = tokenGenerateUtils.parserToUser(token);
|
||||
Long accountId = principal.getId();
|
||||
// String url = "http://18.167.251.121:10002/api/chat_stream";
|
||||
String url = "http://18.167.251.121:2011/api/chat_stream";
|
||||
|
||||
Reference in New Issue
Block a user