parent
44da55b9bf
commit
72807fa65c
@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>huacai</artifactId>
|
||||
<groupId>com.huacai</groupId>
|
||||
<version>3.8.7</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>huacai-framework</artifactId>
|
||||
|
||||
<description>
|
||||
framework框架核心
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- SpringBoot Web容器 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- SpringBoot 拦截器 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 阿里数据库连接池 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 验证码 -->
|
||||
<dependency>
|
||||
<groupId>pro.fessional</groupId>
|
||||
<artifactId>kaptcha</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<groupId>javax.servlet</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- 获取系统信息 -->
|
||||
<dependency>
|
||||
<groupId>com.github.oshi</groupId>
|
||||
<artifactId>oshi-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 系统模块-->
|
||||
<dependency>
|
||||
<groupId>com.huacai</groupId>
|
||||
<artifactId>huacai-system</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@ -0,0 +1,22 @@
|
||||
package com.huacai.framework.config;
|
||||
|
||||
import com.huacai.framework.interceptor.DemoEnvironmentInterceptor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class WebMvcConfig implements WebMvcConfigurer {
|
||||
|
||||
@Autowired
|
||||
private DemoEnvironmentInterceptor demoEnvironmentInterceptor;
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
// 演示环境拦截器
|
||||
registry.addInterceptor(demoEnvironmentInterceptor)
|
||||
.addPathPatterns("/**") // 拦截所有路径
|
||||
.excludePathPatterns("/login", "/logout", "/captchaImage"); // 排除登录等必要接口
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
package com.huacai.framework.config.properties;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
import org.apache.commons.lang3.RegExUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
import com.huacai.common.annotation.Anonymous;
|
||||
|
||||
/**
|
||||
* 设置Anonymous注解允许匿名访问的url
|
||||
*
|
||||
* @author huacai
|
||||
*/
|
||||
@Configuration
|
||||
public class PermitAllUrlProperties implements InitializingBean, ApplicationContextAware
|
||||
{
|
||||
private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private List<String> urls = new ArrayList<>();
|
||||
|
||||
public String ASTERISK = "*";
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet()
|
||||
{
|
||||
RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
|
||||
Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
|
||||
|
||||
map.keySet().forEach(info -> {
|
||||
HandlerMethod handlerMethod = map.get(info);
|
||||
|
||||
// 获取方法上边的注解 替代path variable 为 *
|
||||
Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);
|
||||
Optional.ofNullable(method).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
|
||||
.forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
|
||||
|
||||
// 获取类上边的注解, 替代path variable 为 *
|
||||
Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class);
|
||||
Optional.ofNullable(controller).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
|
||||
.forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext context) throws BeansException
|
||||
{
|
||||
this.applicationContext = context;
|
||||
}
|
||||
|
||||
public List<String> getUrls()
|
||||
{
|
||||
return urls;
|
||||
}
|
||||
|
||||
public void setUrls(List<String> urls)
|
||||
{
|
||||
this.urls = urls;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,181 @@
|
||||
package com.huacai.framework.web.service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.huacai.common.constant.CacheConstants;
|
||||
import com.huacai.common.constant.Constants;
|
||||
import com.huacai.common.constant.UserConstants;
|
||||
import com.huacai.common.core.domain.entity.SysUser;
|
||||
import com.huacai.common.core.domain.model.LoginUser;
|
||||
import com.huacai.common.core.redis.RedisCache;
|
||||
import com.huacai.common.exception.ServiceException;
|
||||
import com.huacai.common.exception.user.BlackListException;
|
||||
import com.huacai.common.exception.user.CaptchaException;
|
||||
import com.huacai.common.exception.user.CaptchaExpireException;
|
||||
import com.huacai.common.exception.user.UserNotExistsException;
|
||||
import com.huacai.common.exception.user.UserPasswordNotMatchException;
|
||||
import com.huacai.common.utils.DateUtils;
|
||||
import com.huacai.common.utils.MessageUtils;
|
||||
import com.huacai.common.utils.StringUtils;
|
||||
import com.huacai.common.utils.ip.IpUtils;
|
||||
import com.huacai.framework.manager.AsyncManager;
|
||||
import com.huacai.framework.manager.factory.AsyncFactory;
|
||||
import com.huacai.framework.security.context.AuthenticationContextHolder;
|
||||
import com.huacai.system.service.ISysConfigService;
|
||||
import com.huacai.system.service.ISysUserService;
|
||||
|
||||
/**
|
||||
* 登录校验方法
|
||||
*
|
||||
* @author huacai
|
||||
*/
|
||||
@Component
|
||||
public class SysLoginService
|
||||
{
|
||||
@Autowired
|
||||
private TokenService tokenService;
|
||||
|
||||
@Resource
|
||||
private AuthenticationManager authenticationManager;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
@Autowired
|
||||
private ISysUserService userService;
|
||||
|
||||
@Autowired
|
||||
private ISysConfigService configService;
|
||||
|
||||
/**
|
||||
* 登录验证
|
||||
*
|
||||
* @param username 用户名
|
||||
* @param password 密码
|
||||
* @param code 验证码
|
||||
* @param uuid 唯一标识
|
||||
* @return 结果
|
||||
*/
|
||||
public String login(String username, String password, String code, String uuid)
|
||||
{
|
||||
// 验证码校验
|
||||
validateCaptcha(username, code, uuid);
|
||||
// 登录前置校验
|
||||
loginPreCheck(username, password);
|
||||
// 用户验证
|
||||
Authentication authentication = null;
|
||||
try
|
||||
{
|
||||
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
|
||||
AuthenticationContextHolder.setContext(authenticationToken);
|
||||
// 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
|
||||
authentication = authenticationManager.authenticate(authenticationToken);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (e instanceof BadCredentialsException)
|
||||
{
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
|
||||
throw new UserPasswordNotMatchException();
|
||||
}
|
||||
else
|
||||
{
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
AuthenticationContextHolder.clearContext();
|
||||
}
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
|
||||
LoginUser loginUser = (LoginUser) authentication.getPrincipal();
|
||||
recordLoginInfo(loginUser.getUserId());
|
||||
// 生成token
|
||||
return tokenService.createToken(loginUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验验证码
|
||||
*
|
||||
* @param username 用户名
|
||||
* @param code 验证码
|
||||
* @param uuid 唯一标识
|
||||
* @return 结果
|
||||
*/
|
||||
public void validateCaptcha(String username, String code, String uuid)
|
||||
{
|
||||
boolean captchaEnabled = configService.selectCaptchaEnabled();
|
||||
if (captchaEnabled)
|
||||
{
|
||||
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
|
||||
String captcha = redisCache.getCacheObject(verifyKey);
|
||||
redisCache.deleteObject(verifyKey);
|
||||
if (captcha == null)
|
||||
{
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
|
||||
throw new CaptchaExpireException();
|
||||
}
|
||||
if (!code.equalsIgnoreCase(captcha))
|
||||
{
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
|
||||
throw new CaptchaException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录前置校验
|
||||
* @param username 用户名
|
||||
* @param password 用户密码
|
||||
*/
|
||||
public void loginPreCheck(String username, String password)
|
||||
{
|
||||
// 用户名或密码为空 错误
|
||||
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
|
||||
{
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
|
||||
throw new UserNotExistsException();
|
||||
}
|
||||
// 密码如果不在指定范围内 错误
|
||||
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|
||||
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH)
|
||||
{
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
|
||||
throw new UserPasswordNotMatchException();
|
||||
}
|
||||
// 用户名不在指定范围内 错误
|
||||
if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|
||||
|| username.length() > UserConstants.USERNAME_MAX_LENGTH)
|
||||
{
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
|
||||
throw new UserPasswordNotMatchException();
|
||||
}
|
||||
// IP黑名单校验
|
||||
String blackStr = configService.selectConfigByKey("sys.login.blackIPList");
|
||||
if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr()))
|
||||
{
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked")));
|
||||
throw new BlackListException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录登录信息
|
||||
*
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
public void recordLoginInfo(Long userId)
|
||||
{
|
||||
SysUser sysUser = new SysUser();
|
||||
sysUser.setUserId(userId);
|
||||
sysUser.setLoginIp(IpUtils.getIpAddr());
|
||||
sysUser.setLoginDate(DateUtils.getNowDate());
|
||||
userService.updateUserProfile(sysUser);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>huacai</artifactId>
|
||||
<groupId>com.huacai</groupId>
|
||||
<version>3.8.7</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>huacai-generator</artifactId>
|
||||
|
||||
<description>
|
||||
generator代码生成
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!--velocity代码生成使用模板 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
<artifactId>velocity-engine-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- collections工具类 -->
|
||||
<dependency>
|
||||
<groupId>commons-collections</groupId>
|
||||
<artifactId>commons-collections</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 通用工具-->
|
||||
<dependency>
|
||||
<groupId>com.huacai</groupId>
|
||||
<artifactId>huacai-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue