Commit 06e97885 authored by wangjinjing's avatar wangjinjing

init

parents
Pipeline #467 failed with stages
in 0 seconds
*.js linguist-language=java
*.css linguist-language=java
*.html linguist-language=java
\ No newline at end of file
/target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/build/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
\ No newline at end of file
name: zhangb211111
\ No newline at end of file
#程序tomcat端口号
port=10300
#数据库
datasource.url=jdbc:oracle:thin:@33.50.1.22:1521:orcl
datasource.username=zn06
datasource.password=znznzn8
datasource.druid.maxActive=20
datasource.druid.validationQuery=SELECT 'x' FROM DUAL
# 图片和视频存储ftp 、
# 格式为:ip地址:端口:用户名:密码
# 端口号一定要写,例如:192.168.2.100:21:reader:reader
ftp.host=33.50.1.22:21:reader:reader
alarm.subscribe.data.key=gs:traff:alarmlist
# 免审标记 0需审核 1免审
alarmrecord.check.enable=1
alarmrecord.check.push.enable=1
#总队情指平台配置
qingzhi.redis.token=gs:traff:qingzhi:token
qingzhi.devicewrite.url=http://33.50.1.213:38080/api/jtldpt/impld/deviceWrite
qingzhi.devicewritesupplier.name=zksy
qingzhi.devicewrite.timeout=5000
qingzhi.eventwrite.url=http://33.50.1.213:38080/api/jtldpt/impld/trafficEventWrite
qingzhi.eventwrite.timeout=5000
qingzhi.login.username=zksy
qingzhi.login.password=zksy@123
qingzhi.login.url=http://33.50.1.213:38080/api/auth/login
qingzhi.login.keepaliveurl=http://33.50.1.213:38080/api/auth/token/keepalive
gs.traff.cloud.department.fileagent.url=http://33.50.1.22:8888/agent/fileAgent?ftpPath=
alarmrecord.check.push.recordtype=1
#程序tomcat端口号
port=10090
#数据库
#datasource.url=jdbc:mysql://192.168.2.100:3306/zndb?characterEncoding=utf8&useSSL=true&serverTimezone=UTC
datasource.url=jdbc:oracle:thin:@192.168.2.100:1521:orcl
datasource.username=zn06
datasource.password=znznzn8
datasource.druid.maxActive=20
datasource.druid.validationQuery=SELECT 'x' FROM DUAL
datasource.driverClassName=oracle.jdbc.driver.OracleDriver
#datasource.driverClassName=com.mysql.cj.jdbc.Driver
#支队编号
message.dept=330300
#消费线程数
message.consumerthreadpoolcoresize=3
#总队接收推送url
department.url=http://localhost:10300/alarmrecord/rec
#发送message到总队超时时间(毫秒)
department.timeout=3000
#支队一次请求推送给总队数据量
department.consumeSize=1
#算法心跳推送到总队地址
arithmeticheartbeats.url=http://localhost:10300/arithmeticheartbeats/heartbeats
#########定时任务########
#sbxx 定时任务启动开关(1为开启)
schedule.sbxx.enable=0
#总队接收sbxx url
schedule.sbxx.url=http://localhost:10300/sbxx/updateSbxx
#sbxx 更新间隔(秒)
schedule.sbxx.interval=5
#sbxx增量时间 使用的系统变化量 CSDL
schedule.sbxx.sbxxXtbhl=gs_traff_sbxx
#sbtdspsr 定时任务启动开关(1为开启)
schedule.sbtdspsr.enable=0
#总队接收sbtdspsr url
schedule.sbtdspsr.url=http://localhost:10300/sbtdspsr/updateSbtdspsr
#sbtdspsr 更新间隔(秒)
schedule.sbtdspsr.interval=5
#sbtdspsr增量时间 使用的系统变化量 CSDL
schedule.sbtdspsr.sbtdspsrXtbhl=gs_traff_sbtdspsr
#ptxzs 定时任务启动开关(1为开启)[废弃]
schedule.ptxzs.enable=0
#总队接收ptxzs url
schedule.ptxzs.url=http://localhost:10300/
#ptxzs 更新间隔(秒)
schedule.ptxzs.interval=5
#ptxzs增量时间 使用的系统变化量 CSDL
schedule.ptxzs.ptxzsXtbhl=gs_traff_ptxzs
#tomcat˿ں
port=10095
\ No newline at end of file
#程序tomcat端口号
port=10700
#数据库
datasource.url=jdbc:oracle:thin:@33.50.1.22:1521:orcl
datasource.username=zn06
datasource.password=znznzn8
datasource.druid.maxActive=20
datasource.druid.validationQuery=SELECT 'x' FROM DUAL
#算法默认类型 0:中科视元 1:海视
alarmfile.datascan.algotype =0
#找N天内的数据进行文件读取并存放到ftp,算法默认7天后失效(单位:天)
alarmfile.datascan.maxday = 7
#重试1小时之前的记录(单位:小时)
alarmfile.retrytime.beforehour = 1
#重试N次后放弃
alarmfile.retrycount.maxvalue = 3
eventwrite.url=http://gs-traff-cloud-department/eventwrite/autoSendEvent
#总队情指平台配置
qingzhi.redis.token=gs:traff:qingzhi:token
qingzhi.login.username=zksy
qingzhi.login.password=zksy@123
qingzhi.login.url=http://33.50.1.213:38080/api/auth/login
qingzhi.login.keepaliveurl=http://33.50.1.213:38080/api/auth/token/keepalive
\ No newline at end of file
#程序tomcat端口号
port=10600
#数据库
datasource.url=jdbc:oracle:thin:@33.50.1.22:1521:orcl
datasource.username=zn06
datasource.password=znznzn8
datasource.druid.maxActive=20
datasource.druid.validationQuery=SELECT 'x' FROM DUAL
#图片视频服务
gs.traff.cloud.web.fileagent.url=http://33.50.1.22:8888/agent/fileAgent?ftpPath=
#情指平台事件推送
eventwrite.url=http://gs-traff-cloud-department/eventwrite/sendEvent
eventwrite.department.timeout=15000
devicewrite.url=http://gs-traff-cloud-department/device/regists
devicewrite.department.timeout=15000
\ No newline at end of file
#程序tomcat端口号
port=10300
#数据库
datasource.url=jdbc:oracle:thin:@33.50.1.22:1521:orcl
datasource.username=zn06
datasource.password=znznzn8
datasource.druid.maxActive=20
datasource.druid.validationQuery=SELECT 'x' FROM DUAL
# 图片和视频存储ftp 、
# 格式为:ip地址:端口:用户名:密码
# 端口号一定要写,例如:192.168.2.100:21:reader:reader
ftp.host=33.65.219.103:21:hzjt:1qaz2wsx
alarm.subscribe.data.key=gs:traff:alarmlist
# 免审标记 0需审核 1免审
alarmrecord.check.enable=1
alarmrecord.check.push.enable=1
#总队情指平台配置
qingzhi.redis.token=gs:traff:qingzhi:token
qingzhi.devicewrite.url=http://33.50.1.213:38080/api/jtldpt/impld/deviceWrite
qingzhi.devicewritesupplier.name=zksy
qingzhi.devicewrite.timeout=5000
qingzhi.eventwrite.url=http://33.50.1.213:38080/api/jtldpt/impld/trafficEventWrite
qingzhi.eventwrite.timeout=5000
qingzhi.login.username=zksy
qingzhi.login.password=zksy@123
qingzhi.login.url=http://33.50.1.213:38080/api/auth/login
qingzhi.login.keepaliveurl=http://33.50.1.213:38080/api/auth/token/keepalive
gs.traff.cloud.department.fileagent.url=http://33.50.1.22:8888/agent/fileAgent?ftpPath=
alarmrecord.check.push.recordtype=1
eventsend.url=http://33.65.219.103:8089/sendEvents
devicesend.url=http://33.65.219.103:8089/traffdevicewriteresult/sendDevices
devicesend.timeout=1000
\ No newline at end of file
#程序tomcat端口号
port=9600
#数据库
datasource.url=jdbc:oracle:thin:@192.168.2.100:1521:orcl
datasource.username=zn06
datasource.password=znznzn8
datasource.druid.maxActive=20
datasource.druid.validationQuery=SELECT 'x' FROM DUAL
#程序tomcat端口号
port=8083
menu=D:/imp/config/im/im-sys/menu.xml
#ice客户端开关[0:停用/1:启用]
scatter.iceclientswitch=1
#初始线程池
ice.threadpool.client.size=5
#线程池的警戒线
ice.threadpool.client.sizewarn=10
#服务端线程最大值
ice.threadpool.client.sizemax=20
#服务端线程最大值
ice.threadpool.server.sizemax=40
#初始线程-最小线程
ice.threadpool.server.sizewarn=40
#ice允许最大内存-单位k
ice.messagesizemax=20480
#ice允许最大内存-单位毫秒
ice.override.timeout=30000
#数据访问中心
dac.dacip=33.50.1.22
dac.port=9900
#数据库
datasource.url=jdbc:oracle:thin:@33.50.1.22:1521:orcl
datasource.username=zn06
datasource.password=znznzn8
datasource.druid.maxActive=20
datasource.druid.validationQuery=SELECT 1 from dual
#平台接入点
pan.port=8886
pan.panIp=33.50.1.22
\ No newline at end of file
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>im.zhaojun</groupId>
<artifactId>yjmqserver</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<relativePath/>
</parent>
<properties>
<!-- 项目编译相关 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<!-- 模板引擎相关 -->
<thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.1.1</thymeleaf-layout-dialect.version>
<!-- 数据库相关 -->
<mybatis.starter.version>1.3.2</mybatis.starter.version>
<druid.starter.version>1.1.10</druid.starter.version>
<pagehelper.starter.verison>1.2.9</pagehelper.starter.verison>
<!-- shiro 相关 -->
<shiro.verison>1.4.0</shiro.verison>
<shiro.redis.version>3.2.3</shiro.redis.version>
<thymeleaf.extras.shiro.version>2.0.0</thymeleaf.extras.shiro.version>
<!-- 工具类相关 -->
<hutool.version>4.1.21</hutool.version>
<oshi.version>3.9.1</oshi.version>
<!-- OAuth2 工具类 -->
<justauth.version>1.4.0</justauth.version>
</properties>
<dependencies>
<!-- spring boot 官方相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 数据库相关, 驱动、mybatis、分页插件 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.starter.version}</version>
</dependency>
<!-- shiro 相关 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.verison}</version>
</dependency>
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>${thymeleaf.extras.shiro.version}</version>
</dependency>
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>${shiro.redis.version}</version>
</dependency>
<!-- 其他工具类相关插件 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>${oshi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>me.zhyd.oauth</groupId>
<artifactId>JustAuth</artifactId>
<version>${justauth.version}</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.12</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>tk.mybatis</groupId>-->
<!-- <artifactId>mapper-spring-boot-starter</artifactId>-->
<!-- <version>2.1.5</version>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<!-- 有人说optional一定要配置成true才有效, 但我调试完感觉不加optional也有效 -->
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.3.8</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.8-beta5</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.8-beta5</version>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.6</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<!-- mqtt -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-mqtt</artifactId>
</dependency>
</dependencies>
<repositories>
<repository>
<id>aliyunmaven</id>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package im.zksy.yjmqserver;
import im.zksy.yjmqserver.system.model.Ftp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
try {
SpringApplication.run(Application.class, args);
}catch (Exception ex){
}
}
@Bean
public Ftp ftpUrl() {
return new Ftp();
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 标记某个方法会引发 Shiro 过滤器链的变化, 将刷新过滤器链.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RefreshFilterChain {
}
\ No newline at end of file
package im.zksy.yjmqserver.common.aop;
import im.zksy.yjmqserver.system.service.ShiroService;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 更新过滤器链
*/
@Aspect
@Component
public class RefreshFilterChainAspect {
@Resource
private ShiroService shiroService;
@Pointcut("@annotation(im.zksy.yjmqserver.common.annotation.RefreshFilterChain)")
public void updateFilterChain() {}
@AfterReturning("updateFilterChain()")
public void doAfter() {
shiroService.updateFilterChain();
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory){
return new RestTemplate(factory);
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(30000);
factory.setReadTimeout(30000);
return factory;
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.config;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import im.zksy.yjmqserver.common.shiro.EnhanceModularRealmAuthenticator;
import im.zksy.yjmqserver.common.shiro.OAuth2Helper;
import im.zksy.yjmqserver.common.shiro.RestShiroFilterFactoryBean;
import im.zksy.yjmqserver.common.shiro.ShiroActionProperties;
import im.zksy.yjmqserver.common.shiro.credential.RetryLimitHashedCredentialsMatcher;
import im.zksy.yjmqserver.common.shiro.filter.OAuth2AuthenticationFilter;
import im.zksy.yjmqserver.common.shiro.filter.RestAuthorizationFilter;
import im.zksy.yjmqserver.common.shiro.filter.RestFormAuthenticationFilter;
import im.zksy.yjmqserver.common.shiro.realm.OAuth2GiteeRealm;
import im.zksy.yjmqserver.common.shiro.realm.OAuth2GithubRealm;
import im.zksy.yjmqserver.common.shiro.realm.UserNameRealm;
import im.zksy.yjmqserver.system.service.ShiroService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import javax.annotation.Resource;
import javax.servlet.Filter;
import java.util.Arrays;
import java.util.Map;
@Configuration
public class ShiroConfig {
@Resource
private OAuth2Helper oAuth2Helper;
@Lazy
@Resource
private ShiroService shiroService;
@Resource
private ShiroActionProperties shiroActionProperties;
@Value("${spring.redis.host}")
private String redisHost;
@Value("${spring.redis.port}")
private Integer redisPort;
@Value("${spring.redis.password}")
private String redisPwd;
@Bean
public RestShiroFilterFactoryBean restShiroFilterFactoryBean(SecurityManager securityManager) {
RestShiroFilterFactoryBean shiroFilterFactoryBean = new RestShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setLoginUrl("/login");
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();
filters.put("authc", new RestFormAuthenticationFilter());
filters.put("perms", new RestAuthorizationFilter());
filters.put("oauth2Authc", new OAuth2AuthenticationFilter(oAuth2Helper));
Map<String, String> urlPermsMap = shiroService.getUrlPermsMap();
shiroFilterFactoryBean.setFilterChainDefinitionMap(urlPermsMap);
return shiroFilterFactoryBean;
}
/**
* 注入 securityManager
*/
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setSessionManager(sessionManager());
securityManager.setRealms(Arrays.asList(userNameRealm(), oAuth2GithubRealm(), oAuth2GiteeRealm()));
ModularRealmAuthenticator authenticator = new EnhanceModularRealmAuthenticator();
securityManager.setAuthenticator(authenticator);
authenticator.setRealms(Arrays.asList(userNameRealm(), oAuth2GithubRealm(), oAuth2GiteeRealm()));
SecurityUtils.setSecurityManager(securityManager);
return securityManager;
}
//
// /**
// * Github 登录 Realm
// */
@Bean
public OAuth2GithubRealm oAuth2GithubRealm() {
return new OAuth2GithubRealm();
}
/**
* Gitee 登录 Realm
*/
@Bean
public OAuth2GiteeRealm oAuth2GiteeRealm() {
return new OAuth2GiteeRealm();
}
/**
* 用户名密码登录 Realm
*/
@Bean
public UserNameRealm userNameRealm() {
UserNameRealm userNameRealm = new UserNameRealm();
userNameRealm.setCredentialsMatcher(hashedCredentialsMatcher());
userNameRealm.setCacheManager(redisCacheManager());
return userNameRealm;
}
/**
* 用户名密码登录密码匹配器
*/
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher() {
return new RetryLimitHashedCredentialsMatcher("md5");
}
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
@Bean
public RedisCacheManager redisCacheManager() {
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(redisManager());
redisCacheManager.setExpire(shiroActionProperties.getPermsCacheTimeout() == null ? 518400 : shiroActionProperties.getPermsCacheTimeout());
redisCacheManager.setPrincipalIdFieldName("userId");
return redisCacheManager;
}
@Bean
public RedisManager redisManager() {
RedisManager redisManager = new RedisManager();
redisManager.setHost(redisHost + ":" + redisPort);
redisManager.setPassword(redisPwd);
return redisManager;
}
@Bean
public RedisSessionDAO redisSessionDAO() {
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setExpire(shiroActionProperties.getSessionTimeout() == null ? 259200 : shiroActionProperties.getSessionTimeout());
redisSessionDAO.setRedisManager(redisManager());
redisSessionDAO.setSessionInMemoryEnabled(false);
return redisSessionDAO;
}
@Bean
public DefaultWebSessionManager sessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setGlobalSessionTimeout(3600000);//一个小时
sessionManager.setSessionDAO(redisSessionDAO());
sessionManager.setSessionIdUrlRewritingEnabled(false);
return sessionManager;
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.config;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
@Configuration
@EnableAsync
public class ThreadConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(8);
executor.setMaxPoolSize(1000);
executor.setQueueCapacity(500);
executor.setKeepAliveSeconds(30000);
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.config;
import im.zksy.yjmqserver.common.interceptor.RequestLogHandlerInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
import java.util.Arrays;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Resource
private RequestLogHandlerInterceptor logHandlerInterceptor;
/**
* 添加拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// registry.addInterceptor(shiroMDCInterceptor)
// .excludePathPatterns(Arrays.asList("/css/**", "/fonts/**", "/images/**", "/js/**", "/lib/**", "/error"));
registry.addInterceptor(logHandlerInterceptor)
.excludePathPatterns(Arrays.asList("/css/**", "/fonts/**", "/images/**", "/js/**", "/lib/**", "/error"));
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.constants;
/**
* 登录认证类型 枚举类
*/
public enum AuthcTypeEnum {
GITHUB("Github"), GITEE("Gitee");
private String description;
AuthcTypeEnum(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
package im.zksy.yjmqserver.common.exception;
public class AuthcTypeNotSupportException extends RuntimeException {
private static final long serialVersionUID = -8964524099437750622L;
public AuthcTypeNotSupportException(String message) {
super(message);
}
}
package im.zksy.yjmqserver.common.exception;
import org.apache.shiro.authc.AuthenticationException;
public class CaptchaIncorrectException extends AuthenticationException {
private static final long serialVersionUID = 2682461331543282364L;
public CaptchaIncorrectException() {
super();
}
}
package im.zksy.yjmqserver.common.exception;
public class DuplicateNameException extends RuntimeException {
private static final long serialVersionUID = 1882153240006350935L;
public DuplicateNameException() {
super();
}
}
package im.zksy.yjmqserver.common.exception;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.WebRequest;
import java.util.HashMap;
import java.util.Map;
@Component
public class MyErrorAttributes extends DefaultErrorAttributes {
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
Map<String, Object> map = new HashMap<>();
Object code = webRequest.getAttribute("code", RequestAttributes.SCOPE_REQUEST);
Object message = webRequest.getAttribute("msg", RequestAttributes.SCOPE_REQUEST);
map.put("code", code);
map.put("msg", null);
return map;
}
}
package im.zksy.yjmqserver.common.exception;
public class TreeCastException extends RuntimeException {
private static final long serialVersionUID = -7358633666514111106L;
public TreeCastException(Throwable cause) {
super(cause);
}
}
package im.zksy.yjmqserver.common.exception;
public class UnknownRedirectUrlException extends RuntimeException{
private static final long serialVersionUID = -4511193905202048700L;
public UnknownRedirectUrlException(String message) {
super(message);
}
}
package im.zksy.yjmqserver.common.exception;
import im.zksy.yjmqserver.common.util.ResultBean;
import org.apache.catalina.connector.ClientAbortException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.NoHandlerFoundException;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@ControllerAdvice
public class WebExceptionHandler {
@Resource
private ShiroFilterFactoryBean shiroFilterFactoryBean;
private static final Logger log = LoggerFactory.getLogger(WebExceptionHandler.class);
@ExceptionHandler
public String authcTypeNotSupport(AuthcTypeNotSupportException e) {
if (log.isDebugEnabled()) {
log.debug(e.getMessage(), e);
}
return generateErrorInfo(ResultBean.FAIL, e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value());
}
@ExceptionHandler
public String unauthenticatedException(UnauthenticatedException e) {
return "redirect:" + shiroFilterFactoryBean.getLoginUrl();
}
@ExceptionHandler
public String unauthorized(NoHandlerFoundException e) {
if (log.isDebugEnabled()) {
log.debug("请求的地址不存在", e);
}
return generateErrorInfo(ResultBean.FAIL, "请求的地址不存在", HttpStatus.NOT_FOUND.value());
}
@ExceptionHandler(value = {UnauthorizedException.class})
public String unauthorized(Exception e) {
if (log.isDebugEnabled()) {
log.debug("无权限");
}
return generateErrorInfo(ResultBean.FAIL, "无权限");
}
@ExceptionHandler
public String unknownAccount(UnknownAccountException e) {
if (log.isDebugEnabled()) {
log.debug("账号不存在");
}
return generateErrorInfo(ResultBean.FAIL, "账号不存在");
}
@ExceptionHandler
public String incorrectCredentials(IncorrectCredentialsException e) {
if (log.isDebugEnabled()) {
log.debug("密码错误");
}
return generateErrorInfo(ResultBean.FAIL, "密码错误");
}
@ExceptionHandler
public String excessiveAttemptsException(ExcessiveAttemptsException e) {
if (log.isDebugEnabled()) {
log.debug("登录失败次数过多");
}
return generateErrorInfo(ResultBean.FAIL, "登录失败次数过多, 请稍后再试");
}
@ExceptionHandler
public String lockedAccount(LockedAccountException e) {
if (log.isDebugEnabled()) {
log.debug("账号已锁定");
}
return "账号已锁定";
}
@ExceptionHandler
public String lockedAccount(CaptchaIncorrectException e) {
if (log.isDebugEnabled()) {
log.debug("验证码错误");
}
return "验证码错误";
}
@ExceptionHandler
public String lockedAccount(DuplicateNameException e) {
if (log.isDebugEnabled()) {
log.debug("用户名已存在");
}
return "用户名已存在";
}
@ExceptionHandler
public String missingRequestParameter(MissingServletRequestParameterException e) {
if (log.isDebugEnabled()) {
log.debug("请求参数无效");
}
return "请求参数缺失";
}
@ExceptionHandler
public String methodArgumentNotValid(BindException e) {
if (log.isDebugEnabled()) {
log.debug("参数校验失败", e);
}
List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
StringBuilder errorMessage = new StringBuilder();
for (int i = 0; i < allErrors.size(); i++) {
ObjectError error = allErrors.get(i);
errorMessage.append(error.getDefaultMessage());
if (i != allErrors.size() - 1) {
errorMessage.append(",");
}
}
return generateErrorInfo(ResultBean.FAIL, errorMessage.toString());
}
@ExceptionHandler
public String all(Exception e) {
String msg = e.getMessage() == null ? "系统出现异常" : e.getMessage();
log.error(msg, e);
generateErrorInfo(ResultBean.FAIL, msg, HttpStatus.INTERNAL_SERVER_ERROR.value());
return "forward:/error";
}
/**
* 生成错误信息, 放到 request 域中.
*
* @param code 错误码
* @param msg 错误信息
* @param httpStatus HTTP 状态码
* @return SpringBoot 默认提供的 /error Controller 处理器
*/
private String generateErrorInfo(int code, String msg, int httpStatus) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
request.setAttribute("code", code);
request.setAttribute("msg", msg);
request.setAttribute("javax.servlet.error.status_code", httpStatus);
return "forward:/error";
}
/**
* 捕获 ClientAbortException 异常, 不做任何处理, 防止出现大量堆栈日志输出, 此异常不影响功能.
*/
@ExceptionHandler({HttpMediaTypeNotAcceptableException.class, ClientAbortException.class})
@ResponseBody
@ResponseStatus
public void clientAbortException(Exception ex) {
if (log.isDebugEnabled()) {
log.debug("出现了断开异常:", ex);
}
}
private String generateErrorInfo(int code, String msg) {
return generateErrorInfo(code, msg, HttpStatus.INTERNAL_SERVER_ERROR.value());
}
}
package im.zksy.yjmqserver.common.interceptor;
import im.zksy.yjmqserver.common.util.IPUtils;
import im.zksy.yjmqserver.system.model.User;
import org.apache.shiro.SecurityUtils;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* MDC 拦截器, 用于将当前操作人的用户名及 IP 添加到 MDC 中. 以在日志中进行显示.
*/
@Component
public class LogMDCInterceptor implements HandlerInterceptor {
private final static String MDC_USERNAME = "username";
private final static String IP = "ip";
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) {
// 如已进行登录, 则获取当前登录者的用户名放入 MDC 中.
String username = "";
User user = (User) SecurityUtils.getSubject().getPrincipal();
if (user != null) {
username = user.getUsername();
}
MDC.put(IP, IPUtils.getIpAddr());
MDC.put(MDC_USERNAME, username);
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) {
String username = MDC.get(MDC_USERNAME);
MDC.remove(username);
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.interceptor;
import cn.hutool.json.JSONUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class RequestLogHandlerInterceptor implements HandlerInterceptor {
private static final Logger log = LoggerFactory.getLogger(RequestLogHandlerInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (log.isDebugEnabled()) {
log.debug("请求 URL:" + request.getRequestURI());
log.debug("请求参数:" + JSONUtil.toJsonStr(request.getParameterMap()));
}
return true;
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.shiro;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.pam.AuthenticationStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.realm.Realm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
/**
* 在 Shiro 使用多 Realm 时, 对于 Realm 中抛出的异常, 他都会进行捕获, 然后输出日志.
* 但我们系统有统一异常处理, 所以不需要他捕获我们的自定义异常, 这里将异常抛出.
*/
public class EnhanceModularRealmAuthenticator extends ModularRealmAuthenticator {
private static final Logger log = LoggerFactory.getLogger(EnhanceModularRealmAuthenticator.class);
/**
* 抛出 realm 中第一个遇到的异常
*/
@Override
protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) {
AuthenticationStrategy strategy = getAuthenticationStrategy();
AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token);
if (log.isTraceEnabled()) {
log.trace("Iterating through {} realms for PAM authentication", realms.size());
}
for (Realm realm : realms) {
aggregate = strategy.beforeAttempt(realm, token, aggregate);
if (realm.supports(token)) {
log.trace("Attempting to authenticate token [{}] using realm [{}]", token, realm);
AuthenticationInfo info;
// 有异常从此处抛出
info = realm.getAuthenticationInfo(token);
aggregate = strategy.afterAttempt(realm, token, info, aggregate, null);
} else {
log.debug("Realm [{}] does not support token {}. Skipping realm.", realm, token);
}
}
aggregate = strategy.afterAllAttempts(token, aggregate);
return aggregate;
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.shiro;
import im.zksy.yjmqserver.common.constants.AuthcTypeEnum;
import im.zksy.yjmqserver.common.exception.AuthcTypeNotSupportException;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.request.AuthGiteeRequest;
import me.zhyd.oauth.request.AuthGithubRequest;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.request.BaseAuthRequest;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Map;
/**
* OAuth2 工具类
*/
@Component
public class OAuth2Helper {
@Resource
private ShiroActionProperties properties;
/**
* 获取所有 OAuth2 配置对象
*/
private Map<AuthcTypeEnum, ShiroActionProperties.Provider> getAllProvider() {
return properties.getOauth2Provider();
}
/**
* 根据类型获取单个 OAuth2 配置对象.
*/
public ShiroActionProperties.Provider getProvider(AuthcTypeEnum identifyType) {
return getAllProvider().get(identifyType);
}
/**
* 根据类型获取 AuthRequest 对象.
*/
public AuthRequest getAuthRequest(AuthcTypeEnum authcTypeEnum) {
ShiroActionProperties.Provider provider = getProvider(authcTypeEnum);
if (provider == null) {
throw new AuthcTypeNotSupportException("系统暂未开启 " + authcTypeEnum.getDescription() + " 登录");
}
BaseAuthRequest authRequest = null;
AuthConfig authConfig = AuthConfig.builder()
.clientId(provider.getClientId())
.clientSecret(provider.getClientSecret())
.redirectUri(provider.getRedirectUrl())
.build();
switch (authcTypeEnum) {
case GITHUB:
authRequest = new AuthGithubRequest(authConfig);
break;
case GITEE:
authRequest = new AuthGiteeRequest(authConfig);
break;
}
return authRequest;
}
/**
* 根据回调地址获取当前认证的类型.
* @param requestURI 回调地址. (尾匹配法)
*/
public AuthcTypeEnum getAuthcTypeByRedirectUrl(String requestURI) {
for (AuthcTypeEnum key : getAllProvider().keySet()) {
String redirectUrl = getProvider(key).getRedirectUrl();
if (redirectUrl.endsWith(requestURI)) {
return key;
}
}
return null;
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.shiro;
import im.zksy.yjmqserver.common.util.WebHelper;
import org.apache.shiro.web.filter.mgt.FilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class RestPathMatchingFilterChainResolver extends PathMatchingFilterChainResolver {
private static final Logger log = LoggerFactory.getLogger(RestPathMatchingFilterChainResolver.class);
@Override
public FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain) {
FilterChainManager filterChainManager = getFilterChainManager();
if (!filterChainManager.hasChains()) {
return null;
}
String requestURI = getPathWithinApplication(request);
// the 'chain names' in this implementation are actually path patterns defined by the user. We just use them
// as the chain name for the FilterChainManager's requirements
for (String pathPattern : filterChainManager.getChainNames()) {
String[] pathPatternArray = pathPattern.split("==");
boolean httpMethodMatchFlag = true;
if (pathPatternArray.length > 1) {
httpMethodMatchFlag = pathPatternArray[1].equals(WebHelper.getRequestHTTPMethod());
}
// 只用过滤器链的 URL 部分与请求的 URL 进行匹配
if (pathMatches(pathPatternArray[0], requestURI) && httpMethodMatchFlag) {
if (log.isTraceEnabled()) {
log.trace("Matched path pattern [" + pathPattern + "] for requestURI [" + requestURI + "]. " +
"Utilizing corresponding filter chain...");
}
return filterChainManager.proxy(originalChain, pathPattern);
}
}
return null;
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.shiro;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.FilterChainManager;
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.mgt.WebSecurityManager;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanInitializationException;
public class RestShiroFilterFactoryBean extends ShiroFilterFactoryBean {
private static final Logger log = LoggerFactory.getLogger(RestShiroFilterFactoryBean.class);
@Override
protected AbstractShiroFilter createInstance() {
log.debug("Creating Shiro Filter instance.");
SecurityManager securityManager = getSecurityManager();
if (securityManager == null) {
String msg = "SecurityManager property must be set.";
throw new BeanInitializationException(msg);
}
if (!(securityManager instanceof WebSecurityManager)) {
String msg = "The security manager does not implement the WebSecurityManager interface.";
throw new BeanInitializationException(msg);
}
FilterChainManager manager = createFilterChainManager();
//Expose the constructed FilterChainManager by first wrapping it in a
// FilterChainResolver implementation. The AbstractShiroFilter implementations
// do not know about FilterChainManagers - only resolvers:
PathMatchingFilterChainResolver chainResolver = new RestPathMatchingFilterChainResolver();
chainResolver.setFilterChainManager(manager);
//Now create a concrete ShiroFilter instance and apply the acquired SecurityManager and built
//FilterChainResolver. It doesn't matter that the instance is an anonymous inner class
//here - we're just using it because it is a concrete AbstractShiroFilter instance that accepts
//injection of the SecurityManager and FilterChainResolver:
return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
}
private static final class SpringShiroFilter extends AbstractShiroFilter {
protected SpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
super();
if (webSecurityManager == null) {
throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
}
setSecurityManager(webSecurityManager);
if (resolver != null) {
setFilterChainResolver(resolver);
}
}
}
}
package im.zksy.yjmqserver.common.shiro;
import im.zksy.yjmqserver.common.constants.AuthcTypeEnum;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@Component
@ConfigurationProperties(prefix = "shiro-action")
public class ShiroActionProperties {
private String superAdminUsername;
private Integer retryCount;
private Boolean loginVerify;
private Integer retryTimeout;
private Integer sessionTimeout;
private Integer permsCacheTimeout;
public String getSuperAdminUsername() {
return superAdminUsername;
}
public void setSuperAdminUsername(String superAdminUsername) {
this.superAdminUsername = superAdminUsername;
}
public Integer getRetryCount() {
return retryCount;
}
public void setRetryCount(Integer retryCount) {
this.retryCount = retryCount;
}
public Integer getRetryTimeout() {
return retryTimeout;
}
public void setRetryTimeout(Integer retryTimeout) {
this.retryTimeout = retryTimeout;
}
public Boolean getLoginVerify() {
return loginVerify;
}
public void setLoginVerify(Boolean loginVerify) {
this.loginVerify = loginVerify;
}
private Map<AuthcTypeEnum, Provider> oauth2Provider = new HashMap<>();
public Map<AuthcTypeEnum, Provider> getOauth2Provider() {
return oauth2Provider;
}
public void setOauth2Provider(Map<AuthcTypeEnum, Provider> oauth2Provider) {
this.oauth2Provider = oauth2Provider;
}
public Integer getSessionTimeout() {
return sessionTimeout;
}
public void setSessionTimeout(Integer sessionTimeout) {
this.sessionTimeout = sessionTimeout;
}
public Integer getPermsCacheTimeout() {
return permsCacheTimeout;
}
public void setPermsCacheTimeout(Integer permsCacheTimeout) {
this.permsCacheTimeout = permsCacheTimeout;
}
@PostConstruct
public void validate() {
Set<String> set = new HashSet<>();
for (Provider provider : this.oauth2Provider.values()) {
// ClientId 不能为空
if (!StringUtils.hasText(provider.getClientId())) {
throw new IllegalStateException("Client id must not be empty.");
}
// ClientSecret 不能为空
if (!StringUtils.hasText(provider.getClientSecret())) {
throw new IllegalStateException("Client secret must not be empty.");
}
// 回调地址不能重复.
if (!set.add(provider.redirectUrl)) {
throw new IllegalStateException("redirectUrl must not be duplicate.");
}
}
}
public static class Provider {
private String clientId;
private String redirectUrl;
private String clientSecret;
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String getRedirectUrl() {
return redirectUrl;
}
public void setRedirectUrl(String redirectUrl) {
this.redirectUrl = redirectUrl;
}
public String getClientSecret() {
return clientSecret;
}
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.shiro.credential;
import im.zksy.yjmqserver.common.shiro.ShiroActionProperties;
import im.zksy.yjmqserver.common.util.IPUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* MD5 密码匹配器
*
* 密码校验失败后计数, 当超出 ${shiro-action.retry-count} 次后, 禁止登录 ${shiro-action.retry-timeout} 秒.
*/
public class RetryLimitHashedCredentialsMatcher extends
HashedCredentialsMatcher {
@Resource
private RedisTemplate<String, AtomicInteger> redisTemplate;
@Resource
private ShiroActionProperties shiroActionProperties;
public RetryLimitHashedCredentialsMatcher(String hashAlgorithmName) {
super(hashAlgorithmName);
}
@Override
public boolean doCredentialsMatch(AuthenticationToken token,
AuthenticationInfo info) {
ValueOperations<String, AtomicInteger> opsForValue = redisTemplate.opsForValue();
String username = (String) token.getPrincipal();
String key = username + IPUtils.getIpAddr();
// 超级管理员不进行登录次数校验.
if (!shiroActionProperties.getSuperAdminUsername().equals(key)) {
AtomicInteger retryCount = opsForValue.get(key);
if (retryCount == null) {
retryCount = new AtomicInteger(0);
}
if (retryCount.incrementAndGet() > shiroActionProperties.getRetryCount()) {
throw new ExcessiveAttemptsException();
}
Integer retryTimeout = shiroActionProperties.getRetryTimeout() == null ? 300 : shiroActionProperties.getRetryTimeout();
opsForValue.set(key, retryCount, retryTimeout, TimeUnit.SECONDS);
}
boolean matches = super.doCredentialsMatch(token, info);
if (matches) {
redisTemplate.delete(key);
}
return matches;
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.shiro.filter;
import im.zksy.yjmqserver.common.constants.AuthcTypeEnum;
import im.zksy.yjmqserver.common.exception.UnknownRedirectUrlException;
import im.zksy.yjmqserver.common.shiro.OAuth2Helper;
import im.zksy.yjmqserver.common.shiro.token.OAuth2Token;
import im.zksy.yjmqserver.common.util.WebHelper;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.util.StringUtils;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
/**
* OAuth2 认证过滤器
*/
public class OAuth2AuthenticationFilter extends AuthenticatingFilter {
private final OAuth2Helper oAuth2Helper;
// oauth2 authc code 参数名
private static final String AUTHC_CODE_PARAM = "code";
public OAuth2AuthenticationFilter(OAuth2Helper oAuth2Helper) {
this.oAuth2Helper = oAuth2Helper;
}
/**
* 使用 OAuth2 服务提供商返回的 code 构建 token
*/
@Override
protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String code = httpRequest.getParameter(AUTHC_CODE_PARAM);
// 根据回调地址, 判断当前的认证类型是什么
String requestURI = httpRequest.getRequestURI();
AuthcTypeEnum authcType = oAuth2Helper.getAuthcTypeByRedirectUrl(requestURI);
if (authcType == null) {
throw new UnknownRedirectUrlException("未知的回调地址:" + requestURI);
}
// 创建 token 到 realm 中执行.
return new OAuth2Token(code, authcType);
}
/**
* 是否允许访问, 直接返回为不允许, 因为本页面只是为了进行认证, 并跳转到首页.
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
return false;
}
/**
* 当 isAccessAllowed 不允许访问时, 判断 oauth2 服务提供商是否返回了错误信息 <p>
* 如果没有返回错误信息, 则判断
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
String error = request.getParameter("error");
String errorDescription = request.getParameter("error_description");
if (!StringUtils.isEmpty(error)) { // 如果服务端返回了错误
WebUtils.issueRedirect(request, response, "/error?error=" + error + "error_description=" + errorDescription);
return false;
}
if (StringUtils.isEmpty(request.getParameter(AUTHC_CODE_PARAM))) {
// 如果用户没有身份验证, 且没有 auth code, 则重定向到登录页面.
saveRequestAndRedirectToLogin(request, response);
return false;
}
// 执行登录操作.
return executeLogin(request, response);
}
// 当登录成功, 跳转到 shiro 配置的 successUrl.
@Override
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,
ServletResponse response) {
WebHelper.redirectUrl("/oauth2/success");
return false;
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.shiro.filter;
import im.zksy.yjmqserver.common.util.IPUtils;
import im.zksy.yjmqserver.common.util.ResultBean;
import im.zksy.yjmqserver.common.util.WebHelper;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.StringUtils;
import org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 修改后的 perms 过滤器, 添加对 AJAX 请求的支持.
*/
public class RestAuthorizationFilter extends PermissionsAuthorizationFilter {
private static final Logger log = LoggerFactory
.getLogger(RestAuthorizationFilter.class);
@Override
protected boolean pathsMatch(String path, ServletRequest request) {
boolean flag;
String requestURI = this.getPathWithinApplication(request);
String[] strings = path.split("==");
if (strings.length <= 1) {
// 普通的 URL, 正常处理
flag = this.pathsMatch(strings[0], requestURI);
} else {
// 获取当前请求的 http method.
String httpMethod = WebUtils.toHttp(request).getMethod().toUpperCase();
// 匹配当前请求的 http method 与 过滤器链中的的是否一致
flag = httpMethod.equals(strings[1].toUpperCase()) && this.pathsMatch(strings[0], requestURI);
}
if (flag) {
log.debug("URL : [{}] matching perms filter : [{}]", requestURI, path);
}
return flag;
}
/**
* 当没有权限被拦截时:
* 如果是 AJAX 请求, 则返回 JSON 数据.
* 如果是普通请求, 则跳转到配置 UnauthorizedUrl 页面.
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
Subject subject = getSubject(request, response);
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
// 如果未登录
if (subject.getPrincipal() == null) {
// AJAX 请求返回 JSON
if (WebHelper.isAjaxRequest(WebUtils.toHttp(request))) {
if (log.isDebugEnabled()) {
log.debug("sessionId: [{}], ip: [{}] 请求 restful url : {}, 未登录被拦截.",
httpServletRequest.getRequestedSessionId(),
IPUtils.getIpAddr(),
this.getPathWithinApplication(request));
}
WebHelper.writeJson(ResultBean.nologerror("未登录"), response);
} else {
// 其他请求跳转到登陆页面
saveRequestAndRedirectToLogin(request, response);
}
} else {
// 如果已登陆, 但没有权限
// 对于 AJAX 请求返回 JSON
if (WebHelper.isAjaxRequest(WebUtils.toHttp(request))) {
if (log.isDebugEnabled()) {
log.debug("用户: [{}] 请求 restful url : {}, 无权限被拦截.", subject.getPrincipal(), this.getPathWithinApplication(request));
}
WebHelper.writeJson(ResultBean.error("无权限"), response);
} else {
// 对于普通请求, 跳转到配置的 UnauthorizedUrl 页面.
// 如果未设置 UnauthorizedUrl, 则返回 401 状态码
String unauthorizedUrl = getUnauthorizedUrl();
if (StringUtils.hasText(unauthorizedUrl)) {
WebUtils.issueRedirect(request, response, unauthorizedUrl);
} else {
WebUtils.toHttp(response).sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
}
}
return false;
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.shiro.filter;
import im.zksy.yjmqserver.common.util.IPUtils;
import im.zksy.yjmqserver.common.util.ResultBean;
import im.zksy.yjmqserver.common.util.WebHelper;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
/**
* 修改后的 authc 过滤器, 添加对 AJAX 请求的支持.
*/
public class RestFormAuthenticationFilter extends FormAuthenticationFilter {
private static final Logger log = LoggerFactory
.getLogger(RestFormAuthenticationFilter.class);
@Override
protected boolean pathsMatch(String path, ServletRequest request) {
boolean flag;
String requestURI = this.getPathWithinApplication(request);
String[] strings = path.split("==");
if (strings.length <= 1) {
// 普通的 URL, 正常处理
flag = this.pathsMatch(strings[0], requestURI);
} else {
// 获取当前请求的 http method.
String httpMethod = WebUtils.toHttp(request).getMethod().toUpperCase();
// 匹配当前请求的 url 和 http method 与过滤器链中的的是否一致
flag = httpMethod.equals(strings[1].toUpperCase()) && this.pathsMatch(strings[0], requestURI);
}
if (flag) {
log.debug("URL : [{}] matching authc filter : [{}]", requestURI, path);
}
return flag;
}
/**
* 当没有权限被拦截时:
* 如果是 AJAX 请求, 则返回 JSON 数据.
* 如果是普通请求, 则跳转到配置 UnauthorizedUrl 页面.
*/
@Override
protected boolean onAccessDenied(ServletRequest request,
ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
if (isLoginRequest(request, response)) {
if (isLoginSubmission(request, response)) {
if (log.isTraceEnabled()) {
log.trace("Login submission detected. Attempting to execute login.");
}
return executeLogin(request, response);
} else {
if (log.isTraceEnabled()) {
log.trace("Login page view.");
}
//allow them to see the login page ;)
return true;
}
} else {
if (log.isTraceEnabled()) {
log.trace("Attempting to access a path which requires authentication. Forwarding to the " +
"Authentication url [" + getLoginUrl() + "]");
}
if (WebHelper.isAjaxRequest(WebUtils.toHttp(request))) {
if (log.isDebugEnabled()) {
log.debug("sessionId: [{}], ip: [{}] 请求 restful url : {}, 未登录被拦截.", httpServletRequest.getRequestedSessionId(), IPUtils.getIpAddr(),
this.getPathWithinApplication(request));
}
WebHelper.writeJson(ResultBean.nologerror("未登录"), response);
} else {
saveRequestAndRedirectToLogin(request, response);
}
return false;
}
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.shiro.realm;
import im.zksy.yjmqserver.common.constants.AuthcTypeEnum;
import org.springframework.stereotype.Component;
/**
* Gitee OAuth2 Realm
*/
@Component
public class OAuth2GiteeRealm extends OAuth2Realm {
@Override
public AuthcTypeEnum getAuthcTypeEnum() {
return AuthcTypeEnum.GITEE;
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.shiro.realm;
import im.zksy.yjmqserver.common.constants.AuthcTypeEnum;
import org.springframework.stereotype.Component;
/**
* Github OAuth2 Realm
*/
@Component
public class OAuth2GithubRealm extends OAuth2Realm {
@Override
public AuthcTypeEnum getAuthcTypeEnum() {
return AuthcTypeEnum.GITHUB;
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.shiro.realm;
import cn.hutool.core.lang.UUID;
import im.zksy.yjmqserver.common.constants.AuthcTypeEnum;
import im.zksy.yjmqserver.common.shiro.OAuth2Helper;
import im.zksy.yjmqserver.common.shiro.token.OAuth2Token;
import im.zksy.yjmqserver.common.util.ShiroUtil;
import im.zksy.yjmqserver.common.util.WebHelper;
import im.zksy.yjmqserver.system.model.User;
import im.zksy.yjmqserver.system.model.UserAuths;
import im.zksy.yjmqserver.system.service.UserAuthsService;
import im.zksy.yjmqserver.system.service.UserService;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.request.ResponseStatus;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Resource;
/**
* OAuth2 通用 Realm.
*/
public abstract class OAuth2Realm extends AuthenticatingRealm {
private static final Logger log = LoggerFactory.getLogger(OAuth2Realm.class);
@Resource
private OAuth2Helper oAuth2Helper;
@Resource
private UserService userService;
@Resource
private UserAuthsService userAuthsService;
/**
* 授权类型, 需子类实现来表示是什么认证类型.
*/
public abstract AuthcTypeEnum getAuthcTypeEnum();
/**
* 调用方法: {@link #getAuthcTypeEnum} 获取认证类型.
* 用来判断该 Realm 是否用来处理此认证类型.
* 并获取该类型对应的 clientId 和 clientSecret 和 redirectUrl.
*/
@Override
public boolean supports(AuthenticationToken token) {
if (token instanceof OAuth2Token) {
OAuth2Token oAuth2Token = (OAuth2Token) token;
AuthcTypeEnum authcTypeEnum = oAuth2Token.getAuthcTypeEnum();
return authcTypeEnum.equals(getAuthcTypeEnum());
}
return false;
}
/**
* 根据 token 获取用户信息.
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
OAuth2Token oAuth2Token = (OAuth2Token) token;
// 获取 code.
String code = oAuth2Token.getAuthCode();
// 根据 code 去 OAuth2 服务商获取用户信息.
AuthUser oauthUser = extractUserInfo(code);
// 获取该账号与当前系统的绑定关系.
UserAuths userAuths;
Subject subject = SecurityUtils.getSubject();
boolean isAuthenticated = subject.isAuthenticated();
if (isAuthenticated) {
userAuths = userAuthsService.selectOneByIdentityTypeAndUserId(getAuthcTypeEnum(), ShiroUtil.getCurrentUser().getUserId());
} else {
userAuths = userAuthsService.selectOneByIdentityTypeAndIdentifier(getAuthcTypeEnum(), oauthUser.getUsername());
}
// 如果未绑定.
if (userAuths == null) {
Integer userId;
// 如果未登录则创建一个用于与之关联.
if (!subject.isAuthenticated()) {
// 创建用户 (这里没有处理用户名重复的问题. 请自行根据业务处理.)
User user = new User();
Integer[] initRoleIds = {2};
user.setUsername(oauthUser.getUsername());
// oauth2 登录的用户, 给予一个随机的密码.
String password = UUID.fastUUID().toString();
String salt = String.valueOf(System.currentTimeMillis());
String encryptPassword = new Md5Hash(password, salt).toString();
user.setPassword(encryptPassword);
user.setSalt(salt);
user.setEmail(oauthUser.getEmail());
user.setStatus("1");
userService.add(user, initRoleIds);
userId = user.getUserId();
} else {
userId = ((User)subject.getPrincipal()).getUserId();
}
// 绑定用户关系.
userAuths = new UserAuths();
userAuths.setUserId(userId);
userAuths.setIdentifier(oauthUser.getUsername());
userAuths.setIdentityType(getAuthcTypeEnum().getDescription());
// 这里存起来 assessToken 用于后续再次调用服务提供商的接口获取相关信息. 虽然此系统后面没用到该参数.
userAuths.setCredential(oauthUser.getToken().getAccessToken());
userAuthsService.insert(userAuths);
}
User user = userService.selectOne(userAuths.getUserId());
log.info(user.toString());
return new SimpleAuthenticationInfo(user, code, getName());
}
// 获取用户信息
private AuthUser extractUserInfo(String code) {
AuthRequest authRequest = oAuth2Helper.getAuthRequest(getAuthcTypeEnum());
AuthResponse authResponse = authRequest.login(code);
// 如果认证失败. 则输出日志, 并将用户重定向到错误页面.
// 这里出错一般原因为程序的 OAuth2 ClientID 或 clientSecret 或 redirectUrl 配置错误.
if (authResponse.getCode() == ResponseStatus.FAILURE.getCode()) {
log.error(authResponse.getMsg());
WebHelper.redirectUrl("/oauth2/error");
}
return (AuthUser) authResponse.getData();
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.shiro.realm;
import im.zksy.yjmqserver.common.shiro.ShiroActionProperties;
import im.zksy.yjmqserver.common.util.ShiroUtil;
import im.zksy.yjmqserver.system.model.User;
import im.zksy.yjmqserver.system.service.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.Set;
/**
* 根据用户名密码校验的 Realm.
*/
@Component
public class UserNameRealm extends AuthorizingRealm {
private static final Logger log = LoggerFactory.getLogger(UserNameRealm.class);
@Resource
private UserService userService;
@Resource
private SessionDAO sessionDAO;
@Resource
private ShiroActionProperties shiroActionProperties;
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof UsernamePasswordToken;
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
log.info("从数据库获取权限信息");
User user = (User) principals.getPrimaryPrincipal();
String username = user.getUsername();
Set<String> roles = userService.selectRoleNameByUserName(username);
Set<String> perms = userService.selectPermsByUsername(username);
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
authorizationInfo.setRoles(roles);
authorizationInfo.setStringPermissions(perms);
return authorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// log.info("从数据库获取认证信息");
String username = (String) token.getPrincipal();
User user = userService.selectOneByUserName(username);
if (user == null) {
throw new UnknownAccountException();
}
// 如果账号被锁定, 则抛出异常, (超级管理员除外)
if (ShiroUtil.USER_LOCK.equals(user.getStatus()) && !shiroActionProperties.getSuperAdminUsername().equals(username)) {
throw new LockedAccountException();
}
return new SimpleAuthenticationInfo(user, user.getPassword(), ByteSource.Util.bytes(user.getSalt()), super.getName());
}
public void clearAuthCacheByUserId(Integer userId) {
// 获取所有 session
Collection<Session> sessions = sessionDAO.getActiveSessions();
for (Session session : sessions) {
// 获取 session 登录信息。
Object obj = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
if (obj instanceof SimplePrincipalCollection) {
// 强转
SimplePrincipalCollection spc = (SimplePrincipalCollection) obj;
User user = new User();
BeanUtils.copyProperties(spc.getPrimaryPrincipal(), user);
// 判断用户, 匹配用户ID.
if (userId.equals(user.getUserId())) {
this.doClearCache(spc);
}
}
}
}
public void clearAllAuthCache() {
// 获取所有 session
Collection<Session> sessions = sessionDAO.getActiveSessions();
for (Session session : sessions) {
// 获取 session 登录信息。
Object obj = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
if (obj instanceof SimplePrincipalCollection) {
// 强转
SimplePrincipalCollection spc = (SimplePrincipalCollection) obj;
User user = new User();
BeanUtils.copyProperties(spc.getPrimaryPrincipal(), user);
this.doClearCache(spc);
}
}
}
/**
* 超级管理员拥有所有权限
*/
@Override
public boolean isPermitted(PrincipalCollection principals, String permission) {
// User user = (User) principals.getPrimaryPrincipal();
// return shiroActionProperties.getSuperAdminUsername().equals(user.getUsername()) || super.isPermitted(principals, permission);
return true;
}
/**
* 超级管理员拥有所有角色
*/
@Override
public boolean hasRole(PrincipalCollection principals, String roleIdentifier) {
User user = (User) principals.getPrimaryPrincipal();
return shiroActionProperties.getSuperAdminUsername().equals(user.getUsername()) || super.hasRole(principals, roleIdentifier);
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.shiro.token;
import im.zksy.yjmqserver.common.constants.AuthcTypeEnum;
import org.apache.shiro.authc.AuthenticationToken;
public class OAuth2Token implements AuthenticationToken {
private static final long serialVersionUID = 636072434492299237L;
private String authCode;
private String principal;
private AuthcTypeEnum authcTypeEnum;
public OAuth2Token(String authCode, AuthcTypeEnum authcTypeEnum) {
this.authCode = authCode;
this.authcTypeEnum = authcTypeEnum;
}
public String getAuthCode() {
return authCode;
}
public void setAuthCode(String authCode) {
this.authCode = authCode;
}
public String getPrincipal() {
return principal;
}
public void setPrincipal(String principal) {
this.principal = principal;
}
public AuthcTypeEnum getAuthcTypeEnum() {
return authcTypeEnum;
}
public void setAuthcTypeEnum(AuthcTypeEnum authcTypeEnum) {
this.authcTypeEnum = authcTypeEnum;
}
@Override
public Object getCredentials() {
return authCode;
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.util;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.util.Random;
/**
* 验证码工具类
*/
public class CaptchaUtil {
/**
* 生成验证码
* @param width 验证码宽度
* @param height 验证码高度
* @param codeCount 验证码个数
* @param lineCount 干扰线个数
* @param lineLenght 干扰线长度
* @return 验证码对象
*/
public static Captcha createCaptcha(int width, int height, int codeCount, int lineCount, int lineLenght) {
BufferedImage image = new BufferedImage(width, height, ColorSpace.TYPE_Lab);
Graphics g = image.getGraphics();
Random random = new Random();
// 取颜色区间中较淡的部分
g.setColor(getRandColor(200, 250));
g.fillRect(0, 0, width, height);
g.setFont(new Font("Times New Roman", Font.PLAIN, 20));
g.setColor(getRandColor(160,200));
// 干扰线
for (int i = 0; i < lineCount; ++i) {
int x = random.nextInt(width);
int y = random.nextInt(height);
int xLength = random.nextInt(lineLenght);
int yLength = random.nextInt(lineLenght);
g.drawLine(x, y, x + xLength, y + yLength);
}
StringBuilder code = new StringBuilder();
// 生成验证码
for (int i = 0; i < codeCount; ++i) {
String rand = String.valueOf(random.nextInt(10));
code.append(rand);
g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
g.drawString(rand, (width / codeCount) * i + (width / codeCount / 2), height / 2 + 9);
}
g.dispose();
return new Captcha(code.toString(), image);
}
/**
* 给定范围内获取颜色值
*/
private static Color getRandColor(int fc, int bc) {
Random random = new Random();
if (fc > 255) {
fc = 255;
}
if (bc > 255) {
bc = 255;
}
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
}
/**
* 验证码对象
*/
public static class Captcha {
private final String code;
private final BufferedImage image;
public String getCode() {
return code;
}
public BufferedImage getImage() {
return image;
}
private Captcha(String code, BufferedImage image) {
this.code = code;
this.image = image;
}
}
}
package im.zksy.yjmqserver.common.util;
import im.zksy.yjmqserver.system.model.ResultInfo;
import org.apache.commons.lang3.time.DateFormatUtils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
public class CommonUtil {
/**************************************正常的result自定义 的*************************************************/
/**
* 请求成功时返回结果
* @param data
* @param code
* @param msg
* @param flag
* @return
*/
public static ResultInfo getResultInfoOk(Object data, Integer code, String msg, boolean flag){
ResultInfo resultInfo = new ResultInfo(code, msg, data, flag);
return resultInfo;
}
public static ResultInfo getResultInfoOk(Object data, Integer code, String msg){
ResultInfo resultInfo = new ResultInfo(code, msg, data, true);
return resultInfo;
}
public static ResultInfo getResultInfoOk(Object data, boolean flag){
ResultInfo resultInfo = new ResultInfo(200, "", data, flag);
return resultInfo;
}
public static ResultInfo getResultInfoOk(Object data){
ResultInfo resultInfo = new ResultInfo(200, "", data, true);
return resultInfo;
}
/**
* 请求失败时返回结果
* @param data
* @param code
* @param msg
* @return
*/
public static ResultInfo getResultInfoFailed(Object data, Integer code, String msg){
ResultInfo resultInfo = new ResultInfo(code, msg, data, false);
return resultInfo;
}
/**
* 得到随机数来做id
* @return
*/
public static String getUUID(){
int length = 8;
String val = "";
Random random = new Random();
//参数length,表示生成几位随机数
for(int i = 0; i < length; i++) {
String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
//输出字母还是数字
if( "char".equalsIgnoreCase(charOrNum) ) {
//输出是大写字母还是小写字母
int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;
val += (char)(random.nextInt(26) + temp);
} else if( "num".equalsIgnoreCase(charOrNum) ) {
val += String.valueOf(random.nextInt(10));
}
}
long millis = System.currentTimeMillis();
return millis+val;
}
/*求余取整*/
public static int getNum(int num,int size){
int a=num/size;
int b=num%size;
if(b==0){
return a;
}else{
return a+1;
}
}
/*
* 传入String类型日期(yyyy-MM-dd HH:mm:ss)
*
* */
public static String dateStrToISO8601(String dateStr){
SimpleDateFormat dtf=new SimpleDateFormat("yyyyMMddHHmmss");
try {
Date date=dtf.parse(dateStr);
String pattern ="yyyy-MM-dd'T'HH:mm:ss.SSSZZ";
String dateISOStr= DateFormatUtils.format(date,pattern);
return dateISOStr;
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
}
package im.zksy.yjmqserver.common.util;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class DateUtil {
public static String getDateStringNoSign(Date date) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
formatter.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
String dateString = formatter.format(date);
return dateString ;
}
}
package im.zksy.yjmqserver.common.util;
import com.sun.org.apache.xpath.internal.operations.Bool;
import org.apache.commons.lang3.time.DateFormatUtils;
import java.lang.management.ManagementFactory;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
/**
* 时间工具类
*/
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
public static String YYYY = "yyyy";
public static String YYYY_MM = "yyyy-MM";
public static final String YYYY_MM_DD = "yyyy-MM-dd";
public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
private static final String[] parsePatterns = {
"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
private static final String format = "yyyy-MM-dd HH:mm:ss";
private static final ThreadLocal<SimpleDateFormat> threadLocal = new
ThreadLocal<>();
/**
* 获取当前Date型日期
*
* @return Date() 当前日期
*/
public static Date getNowDate() {
return new Date();
}
/**
* 获取当前日期, 默认格式为yyyy-MM-dd
*
* @return 日期格式化字符串
*/
public static String getDate() {
return dateTimeNow(YYYY_MM_DD);
}
public static String getTime() {
return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
}
public static String dateTimeNow() {
return dateTimeNow(YYYYMMDDHHMMSS);
}
public static String dateTimeNow(final String format) {
return parseDateToStr(format, new Date());
}
public static String dateTime(final Date date) {
return parseDateToStr(YYYY_MM_DD, date);
}
public static String parseDateToStr(final String format, final Date date) {
return new SimpleDateFormat(format).format(date);
}
/**
* 日期路径 即年/月/日 如2018/08/08
*/
public static String datePath() {
Date now = new Date();
return DateFormatUtils.format(now, "yyyy/MM/dd");
}
/**
* 日期路径 即年/月/日 如20180808
*/
public static String dateTime() {
Date now = new Date();
return DateFormatUtils.format(now, "yyyyMMdd");
}
/**
* 日期型字符串转化为日期 格式
*/
public static Date parseDate(Object str) {
if (str == null) {
return null;
}
try {
return parseDate(str.toString(), parsePatterns);
} catch (ParseException e) {
return null;
}
}
/**
* 计算两个时间差
*/
public static long getDatePoor(Date endDate, Date nowDate) {
long nd = 1000 * 24 * 60 * 60;
long nh = 1000 * 60 * 60;
long nm = 1000 * 60;
// long ns = 1000;
// 获得两个时间的毫秒时间差异
long diff = endDate.getTime() - nowDate.getTime();
// 计算差多少天
long day = diff / nd;
// 计算差多少小时
long hour = diff % nd / nh;
// 计算差多少分钟
long min = diff % nd % nh / nm;
// 计算差多少秒//输出结果
// long sec = diff % nd % nh % nm / ns;
return day;
}
public static String getEndTimestamp(Integer day,String date) {
SimpleDateFormat sdf = null;
sdf = threadLocal.get();
if (sdf == null){
sdf = new SimpleDateFormat(format);
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(parseDate(date));
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.add(Calendar.DAY_OF_MONTH, day);
Date start = calendar.getTime();
Timestamp timestamp = new Timestamp(start.getTime());
return sdf.format(timestamp.getTime());
}
public static String getYestodayTimestamp(Integer day,String date) {
SimpleDateFormat sdf = null;
sdf = threadLocal.get();
if (sdf == null){
sdf = new SimpleDateFormat(format);
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(parseDate(date));
calendar.add(Calendar.DAY_OF_MONTH, day);
Date start = calendar.getTime();
Timestamp timestamp = new Timestamp(start.getTime());
return sdf.format(timestamp.getTime());
}
public static String getLastMinTime(Date newDate, Integer miniuts, String year,Integer yearvalue) {
SimpleDateFormat sdf = null;
sdf = threadLocal.get();
if (sdf == null){
sdf = new SimpleDateFormat(format);
}
Calendar cal = Calendar.getInstance();
cal.setTime(newDate);//设置起时间
if(year.equals("year"))
cal.add(Calendar.YEAR, yearvalue);
else if(year.equals("month")){
cal.add(Calendar.MONTH, yearvalue);
}
else if(year.equals("day")){
cal.add(Calendar.DAY_OF_MONTH, yearvalue);
}
cal.add(Calendar.MINUTE, miniuts);
return sdf.format(cal.getTime());
}
public static String getlastYearTime(Date newDate,Integer year) {
SimpleDateFormat sdf = null;
sdf = threadLocal.get();
if (sdf == null){
sdf = new SimpleDateFormat(format);
}
Calendar cal = Calendar.getInstance();
cal.setTime(newDate);//设置起时间
cal.add(Calendar.YEAR, year);
return sdf.format(cal.getTime());
}
public static String getlastMonthTime(Date newDate,Integer month) {
SimpleDateFormat sdf = null;
sdf = threadLocal.get();
if (sdf == null){
sdf = new SimpleDateFormat(format);
}
Calendar cal= Calendar.getInstance();
cal.setTime(newDate);//设置起时间
cal.add(Calendar.MONTH, month);
return sdf.format(cal.getTime());
}
public static String getlastMonthTimeY_M_D(Date newDate,Integer month) {
SimpleDateFormat sdf = null;
sdf = threadLocal.get();
if (sdf == null){
sdf = new SimpleDateFormat(YYYY_MM_DD);
}
Calendar cal= Calendar.getInstance();
cal.setTime(newDate);//设置起时间
cal.add(Calendar.MONTH, month);
return sdf.format(cal.getTime());
}
public static Date getMonthTimeY_M_D(Date newDate,Integer month) {
SimpleDateFormat sdf = null;
sdf = threadLocal.get();
if (sdf == null){
sdf = new SimpleDateFormat(YYYY_MM_DD);
}
Calendar cal= Calendar.getInstance();
cal.setTime(newDate);//设置起时间
cal.add(Calendar.MONTH, month);
return cal.getTime();
}
public static String getlastDayTime(Date newDate,Integer day) {
SimpleDateFormat sdf = null;
sdf = threadLocal.get();
if (sdf == null){
sdf = new SimpleDateFormat(format);
}
Calendar cal= Calendar.getInstance();
cal.setTime(newDate);//设置起时间
cal.add(Calendar.DAY_OF_MONTH, day);
return sdf.format(cal.getTime());
}
public static String getlastDayTimeY_M_D(Date newDate,Integer day) {
SimpleDateFormat sdf = null;
sdf = threadLocal.get();
if (sdf == null){
sdf = new SimpleDateFormat(YYYY_MM_DD);
}
Calendar cal= Calendar.getInstance();
cal.setTime(newDate);//设置起时间
cal.add(Calendar.DAY_OF_MONTH, day);
return sdf.format(cal.getTime());
}
public static boolean TheSameDay(Date d1,Date d2) {
Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
c1.setTime(d1);
c2.setTime(d2);
return (c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR))
&& (c1.get(Calendar.MONTH) == c2.get(Calendar.MONTH))
&& (c1.get(Calendar.DAY_OF_MONTH) == c2.get(Calendar.DAY_OF_MONTH));
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.util;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ExcelCol {
private String colName;
private String colKey;
}
This diff is collapsed.
package im.zksy.yjmqserver.common.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SuppressWarnings("all")
public class ExportEngine {
private static Log iLog = LogFactory.getLog(ExportEngine.class.getName());
public void exportData(String sheetName, ExcelCol[] headertxt, List<Map> list, HttpServletResponse responses) {
OutputStream os = null;
try {
os = responses.getOutputStream();
responses.reset();// 清空输出流
responses.setHeader("Content-disposition", "attachment; filename=" + (new Date()).getTime() + ".xls");// 设定输出文件头
responses.setContentType("application/msexcel");// 定义输出类型
HSSFWorkbook workbook = new HSSFWorkbook();
// 创建字体对象
HSSFFont font = workbook.createFont();
// 加粗
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
// 字体用什么
font.setFontName("黑体 ");
// 单元格样式对象
HSSFCellStyle cellStyle = workbook.createCellStyle();
// 单元格的字体用什么?就用上面设置好的东西
cellStyle.setFont(font);
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
HSSFSheet sheet = workbook.createSheet(sheetName);
sheet.setDefaultColumnWidth((short) 12);
// 生成表头
HSSFRow row = sheet.createRow((short) 0);
if (headertxt != null && headertxt.length > 0) {
short j = 0;
for (ExcelCol s : headertxt) {
HSSFCell cell1 = row.createCell(j);
cell1.setCellValue(headertxt[j].getColName());
cell1.setCellStyle(cellStyle);
j = (short) (j + 1);
}
}
HSSFCellStyle cs = workbook.createCellStyle();
cs.setAlignment(HSSFCellStyle.ALIGN_CENTER);
// 生成数据
for (int i = 0; i < list.size(); i++) {
HSSFRow datarow = sheet.createRow((short) i + 1);
Map mp = list.get(i);
for (short k = 0; k < headertxt.length; k++) {
HSSFCell datacell = datarow.createCell(k);
datacell.setCellStyle(cs);
datacell.setCellValue(mp.get(headertxt[k].getColKey()) == null ? "" : mp.get(headertxt[k].getColKey()) + "");
}
}
workbook.write(os);
iLog.info("成功导出Excel!");
// 写入文件
} catch (Exception ex) {
iLog.error("导出Excel出错了", ex);
} finally {
try {
os.close();
} catch (Exception ex) {
iLog.error("关闭os失败", ex);
}
}
}
/**
* 导出标准格式Excel的通用方法
*
* @param map
* @param headertxt
* @param list
* 目前只支持List<Map> 形式
* @param responses
*/
public void exportCommData(Map map, ExcelCol[] headertxt, List<HashMap> list, HttpServletResponse responses) {
OutputStream os = null;
try {
os = responses.getOutputStream();
responses.reset();// 清空输出流
String fileName = map.get("fileName").toString();
fileName = toUtf8String(fileName);
responses.setHeader("Content-disposition", "attachment; filename=" + fileName + ".xls");// 设定输出文件头
responses.setContentType("application/msexcel");// 定义输出类型
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFFont font = workbook.createFont();// 创建字体对象
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);// 加粗
font.setFontName("黑体 ");// 设置字体
// Sheet名称
HSSFSheet sheet = workbook.createSheet(map.get("sheetName").toString());
sheet.setDefaultColumnWidth((short) 14);// 默认列宽
// 合并单元格,表头说明信息
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, headertxt.length - 1));
HSSFCellStyle cellStyle2 = setHeadRegionStyle(workbook);// 设置合并头部单元格样式
// 创建第一行
HSSFRow row2 = sheet.createRow(0);
row2.setHeight((short) 400);
HSSFCell cell2 = row2.createCell(0);
cell2.setCellValue(map.get("header").toString());
cell2.setCellStyle(cellStyle2);
for (int k = 1; k < headertxt.length; k++) {
row2.createCell(k).setCellStyle(cellStyle2);
}
HSSFCellStyle cellStyle = setRowsRegionStyle(workbook);// 设置合并行单元格样式
// 创建第二行,生成表头
HSSFRow row = sheet.createRow(1);
if (headertxt != null && headertxt.length > 0) {
short j = 0;
for (ExcelCol s : headertxt) {
HSSFCell cell1 = row.createCell(j);
cell1.setCellValue(headertxt[j].getColName());
cell1.setCellStyle(cellStyle);
j = (short) (j + 1);
}
}
HSSFCellStyle cs = setCommonStyle(workbook);// 设置普通单元格样式
// 生成数据
for (int i = 0; i < list.size(); i++) {
HSSFRow datarow = sheet.createRow((short) i + 2);
Map mp = list.get(i);
for (short k = 0; k < headertxt.length; k++) {
HSSFCell datacell = datarow.createCell(k);
datacell.setCellStyle(cs);
datacell.setCellValue(mp.get(headertxt[k].getColKey()) == null ? "" : mp.get(headertxt[k].getColKey()) + "");
}
}
workbook.write(os);
os.flush();
iLog.info("成功导出Excel!");
// 写入文件
} catch (Exception ex) {
iLog.error("导出Excel出错了", ex);
} finally {
try {
os.close();
} catch (Exception ex) {
iLog.error("关闭os失败", ex);
}
}
}
// 设置头部合并单元格样式
private HSSFCellStyle setHeadRegionStyle(HSSFWorkbook workbook) {
HSSFCellStyle cellStyle = setCommonStyle(workbook);
HSSFFont font = workbook.createFont();
font.setFontHeightInPoints((short) 15);// 字体大小
font.setFontName("宋体");// 字体类型
cellStyle.setFont(font);
return cellStyle;
}
// 设置行合并单元格样式
private HSSFCellStyle setRowsRegionStyle(HSSFWorkbook workbook) {
HSSFFont font = workbook.createFont();
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);// 加粗
font.setFontName("黑体");
HSSFCellStyle cellStyle = setCommonStyle(workbook);
cellStyle.setFont(font);
return cellStyle;
}
// 设置行普通单元格样式
private HSSFCellStyle setCommonStyle(HSSFWorkbook workbook) {
HSSFCellStyle cellStyle = workbook.createCellStyle();
cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);// 左边框
cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);// 上边框
cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);// 右边框
cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);// 下边框
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 水平居中
cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 垂直居中
return cellStyle;
}
// 把字符串转成utf8编码,保证中文文件名不会乱码
public static String toUtf8String(String s) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c >= 0 && c <= 255) {
sb.append(c);
} else {
byte[] b;
try {
b = Character.toString(c).getBytes("utf-8");
} catch (Exception ex) {
b = new byte[0];
}
for (int j = 0; j < b.length; j++) {
int k = b[j];
if (k < 0)
k += 256;
sb.append("%" + Integer.toHexString(k).toUpperCase());
}
}
}
return sb.toString();
}
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
package im.zksy.yjmqserver.common.util;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class IPUtils {
/**
* 获取请求 IP (WEB 服务)
*
* @return IP 地址
*/
public static String getIpAddr() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
if (ip.equals("127.0.0.1")) {
//根据网卡取本机配置的 IP
InetAddress inet = null;
try {
inet = InetAddress.getLocalHost();
ip = inet.getHostAddress();
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 多个代理的情况,第一个 IP 为客户端真实 IP,多个 IP 按照','分割
if (ip != null && ip.length() > 15) {
if (ip.indexOf(",") > 0) {
ip = ip.substring(0, ip.indexOf(","));
}
}
return ip;
}
/**
* 获取当前计算机 IP
*/
public static String getHostIp() {
try {
return InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
return "127.0.0.1";
}
/**
* 获取当前计算机名称
*/
public static String getHostName() {
try {
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
e.printStackTrace();
}
return "未知";
}
}
package im.zksy.yjmqserver.common.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.springframework.stereotype.Component;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
@Component
public class ListToStringHandler extends BaseTypeHandler<List> {
@Override
public void setNonNullParameter(PreparedStatement preparedStatement, int i, List list, JdbcType jdbcType) throws SQLException {
preparedStatement.setString(i, JSON.toJSONString(list));
}
@Override
public List getNullableResult(ResultSet resultSet, String s) throws SQLException {
JSONArray jsonArray = JSONArray.parseArray( resultSet.getString(s));
return jsonArray;
}
@Override
public List getNullableResult(ResultSet resultSet, int i) throws SQLException {
JSONArray jsonArray = JSONArray.parseArray( resultSet.getString(i));
return jsonArray;
}
@Override
public List getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
JSONArray jsonArray = JSONArray.parseArray( callableStatement.getString(i));
return jsonArray;
}
}
package im.zksy.yjmqserver.common.util;
import java.io.Serializable;
import java.util.List;
public class PageResultBean<T> implements Serializable {
private static final long serialVersionUID = 5071118307783022228L;
private long count;
private int code;
private List<T> data;
public PageResultBean(long count, List<T> data) {
this.count = count;
this.data = data;
}
public long getCount() {
return count;
}
public void setCount(long count) {
this.count = count;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public List<T> getData() {
return data;
}
public void setData(List<T> data) {
this.data = data;
}
}
package im.zksy.yjmqserver.common.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexUtils {
/**
* 验证Email
* @param email email地址,格式:zhangsan@zuidaima.com,zhangsan@xxx.com.cn,xxx代表邮件服务商
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkEmail(String email) {
String regex = "\\w+@\\w+\\.[a-z]+(\\.[a-z]+)?";
return Pattern.matches(regex, email);
}
/**
* 验证身份证号码
* @param idCard 居民身份证号码15位或18位,最后一位可能是数字或字母
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkIdCard(String idCard) {
String regex = "[1-9]\\d{13,16}[a-zA-Z0-9]{1}";
return Pattern.matches(regex,idCard);
}
/**
* 验证手机号码(支持国际格式,+86135xxxx...(中国内地),+00852137xxxx...(中国香港))
* @param mobile 移动、联通、电信运营商的号码段
*<p>移动的号段:134(0-8)、135、136、137、138、139、147(预计用于TD上网卡)
*、150、151、152、157(TD专用)、158、159、187(未启用)、188(TD专用)</p>
*<p>联通的号段:130、131、132、155、156(世界风专用)、185(未启用)、186(3g)</p>
*<p>电信的号段:133、153、180(未启用)、189</p>
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkMobile(String mobile) {
String regex = "(\\+\\d+)?1[34578]\\d{9}$";
return Pattern.matches(regex,mobile);
}
/**
* 验证固定电话号码
* @param phone 电话号码,格式:国家(地区)电话代码 + 区号(城市代码) + 电话号码,如:+8602085588447
* <p><b>国家(地区) 代码 :</b>标识电话号码的国家(地区)的标准国家(地区)代码。它包含从 0 到 9 的一位或多位数字,
* 数字之后是空格分隔的国家(地区)代码。</p>
* <p><b>区号(城市代码):</b>这可能包含一个或多个从 0 到 9 的数字,地区或城市代码放在圆括号——
* 对不使用地区或城市代码的国家(地区),则省略该组件。</p>
* <p><b>电话号码:</b>这包含从 0 到 9 的一个或多个数字 </p>
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkPhone(String phone) {
String regex = "(\\+\\d+)?(\\d{3,4}\\-?)?\\d{7,8}$";
return Pattern.matches(regex, phone);
}
/**
* 验证整数(正整数和负整数)
* @param digit 一位或多位0-9之间的整数
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkDigit(String digit) {
String regex = "\\-?[1-9]\\d+";
return Pattern.matches(regex,digit);
}
/**
* 验证整数和浮点数(正负整数和正负浮点数)
* @param decimals 一位或多位0-9之间的浮点数,如:1.23,233.30
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkDecimals(String decimals) {
String regex = "\\-?[1-9]\\d+(\\.\\d+)?";
return Pattern.matches(regex,decimals);
}
/**
* 验证空白字符
* @param blankSpace 空白字符,包括:空格、\t、\n、\r、\f、\x0B
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkBlankSpace(String blankSpace) {
String regex = "\\s+";
return Pattern.matches(regex,blankSpace);
}
/**
* 验证中文
* @param chinese 中文字符
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkChinese(String chinese) {
String regex = "^[\u4E00-\u9FA5]+$";
return Pattern.matches(regex,chinese);
}
/**
* 验证日期(年月日)
* @param birthday 日期,格式:1992-09-03,或1992.09.03
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkBirthday(String birthday) {
String regex = "[1-9]{4}([-./])\\d{1,2}\\1\\d{1,2}";
return Pattern.matches(regex,birthday);
}
/**
* 验证URL地址
* @param url 格式:http://blog.csdn.net:80/xyang81/article/details/7705960? 或 http://www.csdn.net:80
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkURL(String url) {
String regex = "(https?://(w{3}\\.)?)?\\w+\\.\\w+(\\.[a-zA-Z]+)*(:\\d{1,5})?(/\\w*)*(\\??(.+=.*)?(&.+=.*)?)?";
return Pattern.matches(regex, url);
}
/**
* <pre>
* 获取网址 URL 的一级域
* </pre>
*
* @param url
* @return
*/
public static String getDomain(String url) {
Pattern p = Pattern.compile("(?<=http://|\\.)[^.]*?\\.(com|cn|net|org|biz|info|cc|tv)", Pattern.CASE_INSENSITIVE);
// 获取完整的域名
// Pattern p=Pattern.compile("[^//]*?\\.(com|cn|net|org|biz|info|cc|tv)", Pattern.CASE_INSENSITIVE);
Matcher matcher = p.matcher(url);
matcher.find();
return matcher.group();
}
/**
* 匹配中国邮政编码
* @param postcode 邮政编码
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkPostcode(String postcode) {
String regex = "[1-9]\\d{5}";
return Pattern.matches(regex, postcode);
}
/**
* 匹配IP地址(简单匹配,格式,如:192.168.1.1,127.0.0.1,没有匹配IP段的大小)
* @param ipAddress IPv4标准地址
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkIpAddress(String ipAddress) {
String regex = "[1-9](\\d{1,2})?\\.(0|([1-9](\\d{1,2})?))\\.(0|([1-9](\\d{1,2})?))\\.(0|([1-9](\\d{1,2})?))";
return Pattern.matches(regex, ipAddress);
}
/**
* 匹配IP地址(简单匹配,格式,如:192.168.1.1,127.0.0.1,没有匹配IP段的大小)
* @param ipAddress IPv4标准地址
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkFtp(String ipAddress) {
String regex = "(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]";
return Pattern.matches(regex, ipAddress);
}
}
package im.zksy.yjmqserver.common.util;
import java.io.Serializable;
public class ResultBean implements Serializable {
private static final long serialVersionUID = -8276264968757808344L;
private static final int SUCCESS = 0;
public static final int FAIL = -1;
private String msg = "操作成功";
private int code = SUCCESS;
private Object data;
private ResultBean() {
super();
}
private ResultBean(String msg, Object data, int code) {
this.msg = msg;
this.data = data;
this.code = code;
}
public static ResultBean success() {
return success("操作成功");
}
public static ResultBean success(String msg) {
return success(msg, null);
}
public static ResultBean successData(Object data) {
return success("操作成功", data);
}
public static ResultBean success(Object data) {
return success("操作成功", data);
}
public static ResultBean success(String msg, Object data) {
return new ResultBean(msg, data, SUCCESS);
}
public static ResultBean error(String msg) {
ResultBean resultBean = new ResultBean();
resultBean.setCode(FAIL);
resultBean.setMsg(msg);
return resultBean;
}
public static ResultBean nologerror(String msg) {
ResultBean resultBean = new ResultBean();
resultBean.setCode(401);
resultBean.setMsg(msg);
return resultBean;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
package im.zksy.yjmqserver.common.util;
import im.zksy.yjmqserver.system.model.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.UnauthenticatedException;
import org.springframework.stereotype.Component;
@Component
public class ShiroUtil {
public static final String USER_LOCK = "0";
/**
* 获取当前登录用户.
*/
public static User getCurrentUser() {
User user = (User) SecurityUtils.getSubject().getPrincipal();
if (user == null) {
throw new UnauthenticatedException("未登录被拦截");
}
return user;
}
}
package im.zksy.yjmqserver.common.util;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
/**
* Spring Bean 工具类
*/
@Component
public final class SpringBeanUtils implements BeanFactoryPostProcessor {
private static ConfigurableListableBeanFactory beanFactory;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
SpringBeanUtils.beanFactory = beanFactory;
}
public static Object getBean(String name) throws BeansException {
return beanFactory.getBean(name);
}
public static <T> T getBean(Class<T> clz) throws BeansException {
return beanFactory.getBean(clz);
}
public static boolean containsBean(String name) {
return beanFactory.containsBean(name);
}
}
package im.zksy.yjmqserver.common.util;
import java.util.concurrent.*;
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
public class ThreadPoolUtil {
private static BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(5000);
private static final ExecutorService pool =new ThreadPoolExecutor(10, 30, 2L, TimeUnit.MINUTES,
queue , Executors.defaultThreadFactory(), new CallerRunsPolicy());
private static final ScheduledExecutorService schedulepool = Executors.newScheduledThreadPool(2);
public static ScheduledExecutorService getSchedulePool() {
return schedulepool;
}
public static ExecutorService getPool() {
return pool;
}
public static int getQueueSize(){
return queue.size();
}
public static void executeSchedule(Runnable thread){
getSchedulePool().execute(thread);
}
public static void execute(Runnable thread){
getPool().execute(thread);
}
}
This diff is collapsed.
package im.zksy.yjmqserver.common.util;
import cn.hutool.json.JSONUtil;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class WebHelper {
/**
* 是否是Ajax请求
*/
public static boolean isAjaxRequest(HttpServletRequest request) {
String requestedWith = request.getHeader("x-requested-with");
return "XMLHttpRequest".equalsIgnoreCase(requestedWith);
}
/**
* 输出JSON
*/
public static void writeJson(Object object, ServletResponse response) {
PrintWriter out = null;
try {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
out = response.getWriter();
out.write(JSONUtil.toJsonStr(object));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
out.close();
}
}
}
public static void redirectUrl(String redirectUrl) {
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
try {
response.sendRedirect(redirectUrl);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取当前请求的 Http Method
* @return
*/
public static String getRequestHTTPMethod() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
return request.getMethod();
}
}
\ No newline at end of file
package im.zksy.yjmqserver.common.validate.groups;
import javax.validation.groups.Default;
public interface Create extends Default {
}
\ No newline at end of file
package im.zksy.yjmqserver.common.validate.groups;
import javax.validation.groups.Default;
public interface Delete extends Default {
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment