Commit 1714551e authored by wangjinjing's avatar wangjinjing

init

parents
/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.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
eventsend.url=http://localhost:8089/sendEvents
devicesend.url=http://localhost: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>zjgszdVideoAlarmService</artifactId>
<version>0.6</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>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
</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>
</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>
</plugins>
</build>
</project>
\ No newline at end of file
package im.zhaojun;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;
import tk.mybatis.spring.annotation.MapperScan;
@SpringBootApplication
@MapperScan("im.zhaojun.system.mapper")
@PropertySource("file:${spring.profiles.path}")
public class ShiroActionApplication {
public static void main(String[] args) {
SpringApplication.run(ShiroActionApplication.class, args);
}
}
\ No newline at end of file
package im.zhaojun.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 标记注解, 用于记录方法调用日志.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OperationLog {
String value();
}
\ No newline at end of file
package im.zhaojun.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.zhaojun.common.aop;
import im.zhaojun.common.util.IPUtils;
import im.zhaojun.system.model.User;
import im.zhaojun.system.service.LoginLogService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Aspect
@Component
@ConditionalOnProperty(value = "shiro-action.log.login", havingValue = "true")
public class LoginLogAspect {
@Resource
private LoginLogService loginLogService;
@Pointcut("execution(im.zhaojun.common.util.ResultBean im.zhaojun.system.controller..LoginController.login(im.zhaojun.system.model.User, String) )")
public void loginLogPointCut() {}
@After("loginLogPointCut()")
public void recordLoginLog(JoinPoint joinPoint) {
// 获取登陆参数
Object[] args = joinPoint.getArgs();
User user = (User) args[0];
Subject subject = SecurityUtils.getSubject();
String ip = IPUtils.getIpAddr();
loginLogService.addLog(user.getUsername(), subject.isAuthenticated(), ip);
}
}
\ No newline at end of file
package im.zhaojun.common.aop;
import im.zhaojun.common.annotation.OperationLog;
import im.zhaojun.common.util.IPUtils;
import im.zhaojun.common.util.ShiroUtil;
import im.zhaojun.system.mapper.SysLogMapper;
import im.zhaojun.system.model.SysLog;
import im.zhaojun.system.model.User;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Method;
/**
* 操作日志切面.
*/
@Aspect
@Component
@ConditionalOnProperty(value = "shiro-action.log.operation", havingValue = "true")
public class OperationLogAspect {
@Resource
private SysLogMapper sysLogMapper;
@Pointcut("@annotation(im.zhaojun.common.annotation.OperationLog)")
public void pointcut() {
}
@Around(value = "pointcut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
Object result;
long beginTime = System.currentTimeMillis();
// 执行方法
result = point.proceed();
// 执行时长
long time = System.currentTimeMillis() - beginTime;
// 保存日志
saveLog(point, time);
return result;
}
private void saveLog(ProceedingJoinPoint joinPoint, long time) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
SysLog sysLog = new SysLog();
// 获取注解上的操作描述
OperationLog operationLogAnnotation = method.getAnnotation(OperationLog.class);
if (operationLogAnnotation != null) {
sysLog.setOperation(operationLogAnnotation.value());
}
// 请求的方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
sysLog.setMethod(className + "." + methodName + "()");
// 请求的方法参数
Object[] args = joinPoint.getArgs();
LocalVariableTableParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
String[] paramNames = parameterNameDiscoverer.getParameterNames(method);
if (args != null && paramNames != null) {
StringBuilder params = new StringBuilder();
for (int i = 0; i < args.length; i++) {
params.append(" ").append(paramNames[i]).append(": ").append(args[i]);
}
sysLog.setParams(params.toString());
}
sysLog.setIp(IPUtils.getIpAddr());
// 获取当前登录用户名
if (SecurityUtils.getSubject().isAuthenticated()) {
User user = ShiroUtil.getCurrentUser();
sysLog.setUsername(user.getUsername());
}
sysLog.setTime((int) time);
sysLogMapper.insert(sysLog);
}
}
\ No newline at end of file
package im.zhaojun.common.aop;
import im.zhaojun.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.zhaojun.common.annotation.RefreshFilterChain)")
public void updateFilterChain() {}
@AfterReturning("updateFilterChain()")
public void doAfter() {
shiroService.updateFilterChain();
}
}
\ No newline at end of file
package im.zhaojun.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(15000);
factory.setReadTimeout(5000);
return factory;
}
}
\ No newline at end of file
package im.zhaojun.common.config;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import im.zhaojun.common.shiro.EnhanceModularRealmAuthenticator;
import im.zhaojun.common.shiro.OAuth2Helper;
import im.zhaojun.common.shiro.RestShiroFilterFactoryBean;
import im.zhaojun.common.shiro.ShiroActionProperties;
import im.zhaojun.common.shiro.credential.RetryLimitHashedCredentialsMatcher;
import im.zhaojun.common.shiro.filter.OAuth2AuthenticationFilter;
import im.zhaojun.common.shiro.filter.RestAuthorizationFilter;
import im.zhaojun.common.shiro.filter.RestFormAuthenticationFilter;
import im.zhaojun.common.shiro.realm.OAuth2GiteeRealm;
import im.zhaojun.common.shiro.realm.OAuth2GithubRealm;
import im.zhaojun.common.shiro.realm.UserNameRealm;
import im.zhaojun.system.service.MyWebSocketClient;
import im.zhaojun.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.net.URI;
import java.net.URISyntaxException;
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.setSessionDAO(redisSessionDAO());
sessionManager.setSessionIdUrlRewritingEnabled(false);
return sessionManager;
}
}
\ No newline at end of file
package im.zhaojun.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.zhaojun.common.config;
import im.zhaojun.common.interceptor.LogMDCInterceptor;
import im.zhaojun.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;
@Resource
private LogMDCInterceptor shiroMDCInterceptor;
/**
* 添加拦截器
*/
@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.zhaojun.common.config;
import cn.hutool.json.JSONUtil;
import im.zhaojun.system.mapper.AlarmMapper;
import im.zhaojun.system.model.Alarm;
import lombok.extern.slf4j.Slf4j;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.handshake.ServerHandshake;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.net.URI;
@Slf4j
@Component
public class WebSocketConfig {
@Resource
private AlarmMapper alarmMapper;
@Bean
public WebSocketClient webSocketClient() {
try {
WebSocketClient webSocketClient = new WebSocketClient(
new URI("ws://33.55.1.91:8001/api/message/sub/traffic-incident/alarm"), new Draft_6455()) {
@Override
public void onOpen(ServerHandshake handshakedata) {
}
@Override
public void onMessage(String message) {
try {
Alarm alarm = JSONUtil.toBean(message, Alarm.class);
if(alarm.getType().equalsIgnoreCase("TRAFFIC_INCIDENT_ALARM")) {
alarmMapper.insert(alarm);
}
} catch (Exception ex) {
}
}
@Override
public void onClose(int code, String reason, boolean remote) {
}
@Override
public void onError(Exception ex) {
}
};
webSocketClient.connect();
return webSocketClient;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Bean
public WebSocketClient webSocketClient2() {
try {
WebSocketClient webSocketClient = new WebSocketClient(
new URI("ws://localhost:8080/websocket"), new Draft_6455()) {
@Override
public void onOpen(ServerHandshake handshakedata) {
}
@Override
public void onMessage(String message) {
try {
Alarm alarm = JSONUtil.toBean(message, Alarm.class);
alarmMapper.insert(alarm);
if(alarm.getType().equalsIgnoreCase("TRAFFIC_INCIDENT_ALARM")) {
alarmMapper.insert(alarm);
}
} catch (Exception ex) {
}
}
@Override
public void onClose(int code, String reason, boolean remote) {
}
@Override
public void onError(Exception ex) {
}
};
webSocketClient.connect();
return webSocketClient;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
package im.zhaojun.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.zhaojun.common.exception;
public class AuthcTypeNotSupportException extends RuntimeException {
private static final long serialVersionUID = -8964524099437750622L;
public AuthcTypeNotSupportException(String message) {
super(message);
}
}
package im.zhaojun.common.exception;
import org.apache.shiro.authc.AuthenticationException;
public class CaptchaIncorrectException extends AuthenticationException {
private static final long serialVersionUID = 2682461331543282364L;
public CaptchaIncorrectException() {
super();
}
}
package im.zhaojun.common.exception;
public class DuplicateNameException extends RuntimeException {
private static final long serialVersionUID = 1882153240006350935L;
public DuplicateNameException() {
super();
}
}
package im.zhaojun.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", message);
return map;
}
}
package im.zhaojun.common.exception;
public class TreeCastException extends RuntimeException {
private static final long serialVersionUID = -7358633666514111106L;
public TreeCastException(Throwable cause) {
super(cause);
}
}
package im.zhaojun.common.exception;
public class UnknownRedirectUrlException extends RuntimeException{
private static final long serialVersionUID = -4511193905202048700L;
public UnknownRedirectUrlException(String message) {
super(message);
}
}
package im.zhaojun.common.exception;
import im.zhaojun.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 generateErrorInfo(ResultBean.FAIL, "账号已锁定");
}
@ExceptionHandler
public String lockedAccount(CaptchaIncorrectException e) {
if (log.isDebugEnabled()) {
log.debug("验证码错误");
}
return generateErrorInfo(ResultBean.FAIL, "验证码错误");
}
@ExceptionHandler
public String lockedAccount(DuplicateNameException e) {
if (log.isDebugEnabled()) {
log.debug("用户名已存在");
}
return generateErrorInfo(ResultBean.FAIL, "用户名已存在");
}
@ExceptionHandler
public String missingRequestParameter(MissingServletRequestParameterException e) {
if (log.isDebugEnabled()) {
log.debug("请求参数无效");
}
return generateErrorInfo(ResultBean.FAIL, "请求参数缺失");
}
@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.zhaojun.common.information;
import java.math.BigDecimal;
/**
* 精确的浮点数运算
*/
public class Arith {
/**
* 默认除法运算精度
*/
private static final int DEF_DIV_SCALE = 10;
/**
* 这个类不能实例化
*/
private Arith() {
}
/**
* 提供精确的加法运算。
*
* @param v1 被加数
* @param v2 加数
* @return 两个参数的和
*/
public static double add(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
/**
* 提供精确的减法运算。
*
* @param v1 被减数
* @param v2 减数
* @return 两个参数的差
*/
public static double sub(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
/**
* 提供精确的乘法运算。
*
* @param v1 被乘数
* @param v2 乘数
* @return 两个参数的积
*/
public static double mul(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
* 小数点以后10位,以后的数字四舍五入。
*
* @param v1 被除数
* @param v2 除数
* @return 两个参数的商
*/
public static double div(double v1, double v2) {
return div(v1, v2, DEF_DIV_SCALE);
}
/**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
* 定精度,以后的数字四舍五入。
*
* @param v1 被除数
* @param v2 除数
* @param scale 表示表示需要精确到小数点以后几位。
* @return 两个参数的商
*/
public static double div(double v1, double v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
if (b1.compareTo(BigDecimal.ZERO) == 0) {
return BigDecimal.ZERO.doubleValue();
}
return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 提供精确的小数位四舍五入处理。
*
* @param v 需要四舍五入的数字
* @param scale 小数点后保留几位
* @return 四舍五入后的结果
*/
public static double round(double v, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(Double.toString(v));
BigDecimal one = new BigDecimal("1");
return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
}
\ No newline at end of file
package im.zhaojun.common.information;
/**
* 內存相关信息
*/
public class Mem {
/**
* 内存总量
*/
private double total;
/**
* 已用内存
*/
private double used;
/**
* 剩余内存
*/
private double free;
public double getTotal() {
return Arith.div(total, (1024 * 1024 * 1024), 2);
}
public void setTotal(long total) {
this.total = total;
}
public double getUsed() {
return Arith.div(used, (1024 * 1024 * 1024), 2);
}
public void setUsed(long used) {
this.used = used;
}
public double getFree() {
return Arith.div(free, (1024 * 1024 * 1024), 2);
}
public void setFree(long free) {
this.free = free;
}
public double getUsage() {
return Arith.mul(Arith.div(used, total, 4), 100);
}
}
\ No newline at end of file
package im.zhaojun.common.information;
/**
* 系统相关信息
*/
public class Sys {
/**
* 服务器名称
*/
private String computerName;
/**
* 服务器Ip
*/
private String computerIp;
/**
* 项目路径
*/
private String userDir;
/**
* 操作系统
*/
private String osName;
/**
* 系统架构
*/
private String osArch;
public String getComputerName() {
return computerName;
}
public void setComputerName(String computerName) {
this.computerName = computerName;
}
public String getComputerIp() {
return computerIp;
}
public void setComputerIp(String computerIp) {
this.computerIp = computerIp;
}
public String getUserDir() {
return userDir;
}
public void setUserDir(String userDir) {
this.userDir = userDir;
}
public String getOsName() {
return osName;
}
public void setOsName(String osName) {
this.osName = osName;
}
public String getOsArch() {
return osArch;
}
public void setOsArch(String osArch) {
this.osArch = osArch;
}
}
\ No newline at end of file
package im.zhaojun.common.information;
/**
* 系统文件相关信息
*/
public class SysFile {
/**
* 盘符路径
*/
private String dirName;
/**
* 盘符类型
*/
private String sysTypeName;
/**
* 文件类型
*/
private String typeName;
/**
* 总大小
*/
private String total;
/**
* 剩余大小
*/
private String free;
/**
* 已经使用量
*/
private String used;
/**
* 资源的使用率
*/
private double usage;
public String getDirName() {
return dirName;
}
public void setDirName(String dirName) {
this.dirName = dirName;
}
public String getSysTypeName() {
return sysTypeName;
}
public void setSysTypeName(String sysTypeName) {
this.sysTypeName = sysTypeName;
}
public String getTypeName() {
return typeName;
}
public void setTypeName(String typeName) {
this.typeName = typeName;
}
public String getTotal() {
return total;
}
public void setTotal(String total) {
this.total = total;
}
public String getFree() {
return free;
}
public void setFree(String free) {
this.free = free;
}
public String getUsed() {
return used;
}
public void setUsed(String used) {
this.used = used;
}
public double getUsage() {
return usage;
}
public void setUsage(double usage) {
this.usage = usage;
}
}
\ No newline at end of file
package im.zhaojun.common.interceptor;
import im.zhaojun.common.util.IPUtils;
import im.zhaojun.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.zhaojun.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.zhaojun.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.zhaojun.common.shiro;
import im.zhaojun.common.constants.AuthcTypeEnum;
import im.zhaojun.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.zhaojun.common.shiro;
import im.zhaojun.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.zhaojun.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.zhaojun.common.shiro;
import im.zhaojun.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.zhaojun.common.shiro.credential;
import im.zhaojun.common.shiro.ShiroActionProperties;
import im.zhaojun.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.zhaojun.common.shiro.filter;
import im.zhaojun.common.constants.AuthcTypeEnum;
import im.zhaojun.common.exception.UnknownRedirectUrlException;
import im.zhaojun.common.shiro.OAuth2Helper;
import im.zhaojun.common.shiro.token.OAuth2Token;
import im.zhaojun.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.zhaojun.common.shiro.filter;
import im.zhaojun.common.util.IPUtils;
import im.zhaojun.common.util.ResultBean;
import im.zhaojun.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.zhaojun.common.shiro.filter;
import im.zhaojun.common.util.IPUtils;
import im.zhaojun.common.util.ResultBean;
import im.zhaojun.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.zhaojun.common.shiro.realm;
import im.zhaojun.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.zhaojun.common.shiro.realm;
import im.zhaojun.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.zhaojun.common.shiro.realm;
import cn.hutool.core.lang.UUID;
import im.zhaojun.common.constants.AuthcTypeEnum;
import im.zhaojun.common.shiro.OAuth2Helper;
import im.zhaojun.common.shiro.token.OAuth2Token;
import im.zhaojun.common.util.ShiroUtil;
import im.zhaojun.common.util.WebHelper;
import im.zhaojun.system.model.User;
import im.zhaojun.system.model.UserAuths;
import im.zhaojun.system.service.UserAuthsService;
import im.zhaojun.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.zhaojun.common.shiro.realm;
import im.zhaojun.common.shiro.ShiroActionProperties;
import im.zhaojun.common.util.ShiroUtil;
import im.zhaojun.system.model.User;
import im.zhaojun.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);
}
/**
* 超级管理员拥有所有角色
*/
@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.zhaojun.common.shiro.token;
import im.zhaojun.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.zhaojun.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.zhaojun.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;
}
/**
* 获取指定时间的凌晨时间
* @author : fyk
* @create : 2019/10/9 9:58
* @param: day 天 为0 就是获取当天 1 往后加一天 -1 前退一天
**/
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());
}
/**
* 获取指定前一天时间
* @author : fyk
* @create : 2019/10/9 9:58
* @param: day 天 为0 就是获取当天 1 往后加一天 -1 前退一天
**/
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.zhaojun.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.zhaojun.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
package im.zhaojun.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.zhaojun.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.zhaojun.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.zhaojun.common.util;
import im.zhaojun.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.zhaojun.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.zhaojun.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.zhaojun.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.zhaojun.common.validate.groups;
import javax.validation.groups.Default;
public interface Create extends Default {
}
\ No newline at end of file
package im.zhaojun.common.validate.groups;
import javax.validation.groups.Default;
public interface Delete extends Default {
}
\ No newline at end of file
package im.zhaojun.common.validate.groups;
import javax.validation.groups.Default;
public interface Update extends Default {
}
\ No newline at end of file
package im.zhaojun.system.controller;
import com.github.pagehelper.PageInfo;
import im.zhaojun.common.annotation.OperationLog;
import im.zhaojun.common.util.PageResultBean;
import im.zhaojun.common.util.ResultBean;
import im.zhaojun.system.model.Code;
import im.zhaojun.system.service.CodeService;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@RestController
@RequestMapping("/code")
public class CodeController {
@Resource
private CodeService codeService;
@OperationLog("获取code列表")
@GetMapping("/list")
@ResponseBody
public PageResultBean<Code> getList(@RequestParam(value = "page", defaultValue = "1") int page,
@RequestParam(value = "limit", defaultValue = "10") int limit) {
List<Code> codes = codeService.selectAllWithKey(page, limit);
PageInfo<Code> userPageInfo = new PageInfo<>(codes);
return new PageResultBean<>(userPageInfo.getTotal(), userPageInfo.getList());
}
@OperationLog("获取指定type的code列表")
@GetMapping("/list/{typeid}")
@ResponseBody
public ResultBean getList(@PathVariable("typeid") String typeid) {
List<Code> codes = codeService.selectAllWithType(typeid);
return ResultBean.success(codes);
};
@OperationLog("更新code")
@PostMapping("/update")
public ResultBean update(@RequestBody List<Code> codelist) {
int result = codeService.updatecode(codelist);
return ResultBean.success();
}
@OperationLog("更新用户列表")
@GetMapping("/codetest")
public void test() {
List<Code> codes = codeService.selectAllWithKey(1, 10);
}
@OperationLog("更新code time")
@PostMapping("/updatetime")
public ResultBean updatetime(@RequestBody List<Code> codelist) {
int result = codeService.updatetime(codelist);
return ResultBean.success();
}
@OperationLog("禁用账号")
@PostMapping("/{codeId}/disable")
@ResponseBody
public ResultBean disable(@PathVariable("codeId") String codeId) {
return ResultBean.success(codeService.disableCodeByCodeID(codeId));
}
@OperationLog("激活账号")
@PostMapping("/{codeId}/enable")
@ResponseBody
public ResultBean enable(@PathVariable("codeId") String codeId) {
return ResultBean.success(codeService.enableCodeByCodeID(codeId));
}
@GetMapping("/update/{name}/{alarmlevel}")
public ResultBean update(@PathVariable("name") String name, @PathVariable("alarmlevel") String alarmlevel) {
//更新手动状态
return ResultBean.success(codeService.updatemanualcode(name,alarmlevel));
}
}
\ No newline at end of file
package im.zhaojun.system.controller;
import im.zhaojun.common.util.ResultBean;
import im.zhaojun.system.model.vo.UrlVO;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import javax.annotation.Resource;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@Controller
public class CommonPageController {
@Resource
private WebApplicationContext applicationContext;
@GetMapping("/403")
public String forbidden() {
return "error/403";
}
@GetMapping("/404")
public String unauthorizedPage() {
return "error/404";
}
@GetMapping("/500")
public String error() {
return "error/500";
}
/**
* 获取 @RequestMapping 中配置的所有 URL.
* @param keyword 关键字: 过滤条件
* @return URL 列表.
*/
@GetMapping("/system/urls")
@ResponseBody
public ResultBean getUrl(@RequestParam(defaultValue = "") String keyword) {
RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
// 获取url与类和方法的对应信息
Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
Set<UrlVO> urlSet = new HashSet<>();
for (Map.Entry<RequestMappingInfo, HandlerMethod> m : map.entrySet()) {
// URL 类型, JSON 还是 VIEW
String type = "view";
if (isResponseBodyUrl(m.getValue())){
type = "json";
}
// URL 地址和 URL 请求 METHOD
RequestMappingInfo info = m.getKey();
PatternsRequestCondition p = info.getPatternsCondition();
// 一个 @RequestMapping, 可能有多个 URL.
for (String url : p.getPatterns()) {
// 根据 keyword 过滤 URL
if (url.contains(keyword)) {
// 获取这个 URL 支持的所有 http method, 多个以逗号分隔, 未配置返回 ALL.
Set<RequestMethod> methods = info.getMethodsCondition().getMethods();
String method = "ALL";
if (methods.size() != 0) {
method = StringUtils.collectionToDelimitedString(methods, ",");
}
urlSet.add(new UrlVO(url, method, type));
}
}
}
return ResultBean.success(urlSet);
}
/**
* 判断是否返回 JSON, 判断方式有两种:
* 1. 类上标有 ResponseBody 或 RestController 注解
* 2. 方法上标有 ResponseBody 注解
*/
private boolean isResponseBodyUrl(HandlerMethod handlerMethod) {
return handlerMethod.getBeanType().getDeclaredAnnotation(RestController.class) != null ||
handlerMethod.getBeanType().getDeclaredAnnotation(ResponseBody.class) != null ||
handlerMethod.getMethodAnnotation(ResponseBody.class) != null;
}
}
\ No newline at end of file
package im.zhaojun.system.controller;
import im.zhaojun.common.annotation.OperationLog;
import im.zhaojun.common.shiro.ShiroActionProperties;
import im.zhaojun.common.util.ResultBean;
import im.zhaojun.common.util.TreeUtil;
import im.zhaojun.system.model.Dept;
import im.zhaojun.system.model.DeptVideo;
import im.zhaojun.system.service.DeptService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@Controller
@RequestMapping("/dept")
public class DeptController {
@Resource
private DeptService deptService;
@Resource
private ShiroActionProperties shiroActionProperties;
@Value("${managername}")
private String managername;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@GetMapping("/index")
public String index() {
return "dept/dept-list";
}
@OperationLog("获取部门列表")
@GetMapping("/list")
@ResponseBody
public ResultBean getList(@RequestParam(value="parentId",required = false) Integer parentId) {
List<Dept> deptList = deptService.selectByParentId(parentId);
return ResultBean.success(deptList);
}
@GetMapping("/tree/root")
@ResponseBody
public ResultBean treeAndRoot() {
return ResultBean.success(deptService.selectAllTreeAndRoot());
}
@GetMapping("/tree")
@ResponseBody
public ResultBean tree() {
return ResultBean.success(deptService.selectAllTree());
}
@GetMapping
public String add() {
return "dept/dept-add";
}
@OperationLog("新增部门")
@ResponseBody
@RequestMapping(value = "/add", method = RequestMethod.POST)
public ResultBean add(Dept dept) {
if(null==dept.getDeptId() ||dept.getDeptId().equals(""))
{
dept.setDeptId(deptService.selectMaxOrderNum()+1);
}
dept.setCreateTime(sdf.format(new Date()));
dept.setModifyTime(dept.getCreateTime());
return ResultBean.success(deptService.insert(dept));
}
@OperationLog("删除部门")
@DeleteMapping("/{deptId}")
@ResponseBody
public ResultBean delete(@PathVariable("deptId") Integer deptId) {
deptService.deleteCascadeByID(deptId);
return ResultBean.success();
}
@OperationLog("修改部门")
@ResponseBody
@RequestMapping(value = "/update", method = RequestMethod.POST)
public ResultBean update(Dept dept) {
dept.setModifyTime(sdf.format(new Date()));
deptService.updateByPrimaryKey(dept);
return ResultBean.success();
}
@GetMapping("/{deptId}")
public ResultBean update(@PathVariable("deptId") String deptId) {
List<Map> dept = deptService.selectByPrimaryKey(deptId);
return ResultBean.success(dept);
}
@GetMapping("/getDeptParent/{deptId}")
@ResponseBody
public ResultBean getDeptParent(@PathVariable("deptId") String deptId) {
List<Map> dept = deptService.selectByPrimaryKey(deptId);
return ResultBean.success(dept);
}
@OperationLog("调整部门排序")
@PostMapping("/swap")
@ResponseBody
public ResultBean swapSort(Integer currentId, Integer swapId) {
deptService.swapSort(currentId, swapId);
return ResultBean.success();
}
@OperationLog("查询部门及監控")
@GetMapping("/listvideo")
@ResponseBody
public ResultBean listvideo( @RequestParam("deptId") String deptId,@RequestParam("username") String username,@RequestParam("tdmc")String tdmc) {
if (null!=username && (shiroActionProperties.getSuperAdminUsername().equals(username)
||username.equalsIgnoreCase(managername))) {
deptId = "0";
username=null;
}
List<DeptVideo> deptlist=deptService.listvideo(deptId, username,tdmc);
return ResultBean.success(deptlist);
}
@OperationLog("查询部门及監控")
@GetMapping("/listvideotree")
@ResponseBody
public ResultBean listvideotree( @RequestParam("deptId") String deptId,@RequestParam("username") String username,@RequestParam("tdmc")String tdmc) {
if (null!=username && (shiroActionProperties.getSuperAdminUsername().equals(username)
||username.equalsIgnoreCase(managername))) {
deptId = "0";
username=null;
}
List<DeptVideo> deptlist=deptService.listvideo(deptId, username,tdmc);
List<DeptVideo> list= TreeUtil.toTree(deptlist,"deptId","parentId","nodes",DeptVideo.class,deptId);
return ResultBean.success(list);
}
@OperationLog("查询部门及其子節點")
@GetMapping("/listChildDept")
@ResponseBody
public ResultBean listChildDept( @RequestParam("deptId") Integer deptId,@RequestParam("username") String username) {
if (null!=username && (shiroActionProperties.getSuperAdminUsername().equals(username)
||username.equalsIgnoreCase(managername))) {
deptId =0;
username=null;
}
List<Dept> deptlist=deptService.selectDeptChildren(deptId, username);
return ResultBean.success(deptlist);
}
@OperationLog("更新部門默認監控")
@PostMapping("/updateDefaultVideo")
@ResponseBody
public ResultBean updateDefaultVideo( @RequestParam("deptId") String deptId,@RequestParam("videoId") String videoId) {
int result=deptService.updateDefaultVideoByDeptId(deptId, videoId);
if(result>0) {
return ResultBean.success();
}else {
return ResultBean.error("更新失敗");
}
}
@OperationLog("查詢部門默認監控")
@GetMapping("/queryDefaultVideoId")
@ResponseBody
public ResultBean queryDefaultVideo( @RequestParam("deptId") String deptId) {
return ResultBean.success(deptService.selectDefaultVideoByDeptId(deptId));
}
@OperationLog("查詢所有部門默認監控")
@GetMapping("/queryAllDefaultVideo")
@ResponseBody
public ResultBean queryAllDefaultVideo( @RequestParam("deptId") String deptId) {
return ResultBean.success(deptService.selectAllDefaultVideo(deptId));
}
@OperationLog("新增部門默認監控")
@PostMapping("/insertDefaultVideo")
@ResponseBody
public ResultBean insertDefaultVideo( @RequestParam("deptId") String deptId,
@RequestParam("videoId[]") List<String> videoId) {
for(String videoid:videoId)
{
//判断是否存在
int result= deptService.selectExistsDefaultVideo(deptId,videoid);
if(result==0){
deptService.insertDefaultVideo(deptId,videoid);
}
}
return ResultBean.success();
}
@OperationLog("查询所有监控")
@GetMapping("/listAllvideoIdsByDeptid")
@ResponseBody
public ResultBean listAllvideoIdsByDeptid(@RequestParam("deptid") String deptid) {
List<Map> deptList = deptService.listAllvideoIdsByDeptid(deptid);
return ResultBean.success(deptList);
}
}
package im.zhaojun.system.controller;
import im.zhaojun.common.annotation.OperationLog;
import im.zhaojun.common.shiro.ShiroActionProperties;
import im.zhaojun.common.util.ResultBean;
import im.zhaojun.system.model.DeptTree;
import im.zhaojun.system.service.DeptService;
import im.zhaojun.system.service.DeptTreeService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
@Controller
@RequestMapping("/depttree")
public class DeptTreeController {
@Resource
private DeptTreeService deptTreeService;
@Resource
private ShiroActionProperties shiroActionProperties;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@GetMapping("/index")
public String index() {
return "dept/dept-list";
}
@OperationLog("获取部门列表")
@GetMapping("/list")
@ResponseBody
public ResultBean getList(@RequestParam(required = false) String parentId) {
List<DeptTree> deptList = deptTreeService.selectByParentId(parentId);
return ResultBean.success(deptList);
}
@GetMapping("/tree/root")
@ResponseBody
public ResultBean treeAndRoot() {
return ResultBean.success(deptTreeService.selectAllDeptTreeAndRoot());
}
@GetMapping("/tree")
@ResponseBody
public ResultBean tree() {
return ResultBean.success(deptTreeService.selectAllDeptTree("0")
);
}
@GetMapping
public String add() {
return "dept/dept-add";
}
// @OperationLog("新增部门")
// @PostMapping
// @ResponseBody
// public ResultBean add(DeptTree dept) {
// if(null==dept.getDeptId() ||dept.getDeptId().equals(""))
// {
// dept.setDeptId(deptTreeService.selectMaxOrderNum()+1);
// }
// dept.setCreateTime(sdf.format(new Date()));
// dept.setModifyTime(dept.getCreateTime());
// return ResultBean.success(deptTreeService.insert(dept));
// }
@OperationLog("删除部门")
@DeleteMapping("/{deptId}")
@ResponseBody
public ResultBean delete(@PathVariable("deptId") String deptId) {
deptTreeService.deleteCascadeByID(deptId);
return ResultBean.success();
}
@OperationLog("修改部门")
@PutMapping
@ResponseBody
public ResultBean update(DeptTree dept) {
dept.setModifyTime(dept.getCreateTime());
deptTreeService.updateByPrimaryKey(dept);
return ResultBean.success();
}
@GetMapping("/{deptId}")
public String update(@PathVariable("deptId") String deptId, Model model) {
DeptTree dept = deptTreeService.selectByPrimaryKey(deptId);
model.addAttribute("dept", dept);
return "dept/dept-add";
}
@OperationLog("调整部门排序")
@PostMapping("/swap")
@ResponseBody
public ResultBean swapSort(Integer currentId, Integer swapId) {
deptTreeService.swapSort(currentId, swapId);
return ResultBean.success();
}
@OperationLog("获取部门列表")
@GetMapping("/listByUsername")
@ResponseBody
public ResultBean listByUsername(@RequestParam(required = false) String parentId,String username) {
if (null!=username && shiroActionProperties.getSuperAdminUsername().equals(username)) {
parentId = "-1";
}
List<DeptTree> deptList = deptTreeService.selectAllDeptTree(parentId);
return ResultBean.success(deptList);
}
}
package im.zhaojun.system.controller;
import com.github.pagehelper.PageInfo;
import im.zhaojun.common.annotation.OperationLog;
import im.zhaojun.common.util.PageResultBean;
import im.zhaojun.system.model.LoginLog;
import im.zhaojun.system.service.LoginLogService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import java.util.List;
@Controller
@RequestMapping("/log/login")
public class LoginLogController {
@Resource
private LoginLogService loginLogService;
@GetMapping("/index")
public String index() {
return "log/login-logs";
}
@OperationLog("查看登录日志")
@GetMapping("/list")
@ResponseBody
public PageResultBean<LoginLog> getList(@RequestParam(value = "page", defaultValue = "1") int page,
@RequestParam(value = "limit", defaultValue = "10")int limit) {
List<LoginLog> loginLogs = loginLogService.selectAll(page, limit);
PageInfo<LoginLog> rolePageInfo = new PageInfo<>(loginLogs);
return new PageResultBean<>(rolePageInfo.getTotal(), rolePageInfo.getList());
}
}
This diff is collapsed.
This diff is collapsed.
package im.zhaojun.system.controller;
import im.zhaojun.common.util.ResultBean;
import org.apache.shiro.SecurityUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 安全相关 Controller
*/
@Controller
@RequestMapping("/security")
public class SecurityController {
/**
* 判断当前登录用户是否有某权限
*/
@GetMapping("/hasPermission/{perms}")
@ResponseBody
public ResultBean hasPermission(@PathVariable("perms") String perms) {
return ResultBean.success(SecurityUtils.getSubject().isPermitted(perms));
}
}
This diff is collapsed.
package im.zhaojun.system.mapper;
import im.zhaojun.system.model.Alarm;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface AlarmMapper {
int insert(Alarm alarm);
}
\ 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.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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