delete ruoyi 1.1.6
This commit is contained in:
@ -1,178 +0,0 @@
|
||||
package com.ruoyi.framework.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import com.ruoyi.common.utils.AddressUtils;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.Signature;
|
||||
import org.aspectj.lang.annotation.AfterReturning;
|
||||
import org.aspectj.lang.annotation.AfterThrowing;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.ruoyi.common.constant.UserConstants;
|
||||
import com.ruoyi.common.utils.ServletUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.security.ShiroUtils;
|
||||
import com.ruoyi.framework.aspectj.lang.annotation.Log;
|
||||
import com.ruoyi.project.monitor.operlog.domain.OperLog;
|
||||
import com.ruoyi.project.monitor.operlog.service.IOperLogService;
|
||||
import com.ruoyi.project.system.user.domain.User;
|
||||
|
||||
/**
|
||||
* 操作日志记录处理
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
@EnableAsync
|
||||
public class LogAspect
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
|
||||
|
||||
@Autowired
|
||||
private IOperLogService operLogService;
|
||||
|
||||
// 配置织入点
|
||||
@Pointcut("@annotation(com.ruoyi.framework.aspectj.lang.annotation.Log)")
|
||||
public void logPointCut()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* 前置通知 用于拦截操作
|
||||
*
|
||||
* @param joinPoint 切点
|
||||
*/
|
||||
@AfterReturning(pointcut = "logPointCut()")
|
||||
public void doBefore(JoinPoint joinPoint)
|
||||
{
|
||||
handleLog(joinPoint, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截异常操作
|
||||
*
|
||||
* @param joinPoint
|
||||
* @param e
|
||||
*/
|
||||
@AfterThrowing(value = "logPointCut()", throwing = "e")
|
||||
public void doAfter(JoinPoint joinPoint, Exception e)
|
||||
{
|
||||
handleLog(joinPoint, e);
|
||||
}
|
||||
|
||||
@Async
|
||||
protected void handleLog(final JoinPoint joinPoint, final Exception e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 获得注解
|
||||
Log controllerLog = getAnnotationLog(joinPoint);
|
||||
if (controllerLog == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取当前的用户
|
||||
User currentUser = ShiroUtils.getUser();
|
||||
|
||||
// *========数据库日志=========*//
|
||||
OperLog operLog = new OperLog();
|
||||
operLog.setStatus(UserConstants.NORMAL);
|
||||
// 请求的地址
|
||||
String ip = ShiroUtils.getIp();
|
||||
operLog.setOperIp(ip);
|
||||
// 操作地点
|
||||
operLog.setOperLocation(AddressUtils.getRealAddressByIP(ip));
|
||||
|
||||
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
|
||||
if (currentUser != null)
|
||||
{
|
||||
operLog.setLoginName(currentUser.getLoginName());
|
||||
operLog.setDeptName(currentUser.getDept().getDeptName());
|
||||
}
|
||||
|
||||
if (e != null)
|
||||
{
|
||||
operLog.setStatus(UserConstants.EXCEPTION);
|
||||
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
|
||||
}
|
||||
// 设置方法名称
|
||||
String className = joinPoint.getTarget().getClass().getName();
|
||||
String methodName = joinPoint.getSignature().getName();
|
||||
operLog.setMethod(className + "." + methodName + "()");
|
||||
// 处理设置注解上的参数
|
||||
getControllerMethodDescription(controllerLog, operLog);
|
||||
// 保存数据库
|
||||
operLogService.insertOperlog(operLog);
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
// 记录本地异常日志
|
||||
log.error("==前置通知异常==");
|
||||
log.error("异常信息:{}", exp.getMessage());
|
||||
exp.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取注解中对方法的描述信息 用于Controller层注解
|
||||
*
|
||||
* @param joinPoint 切点
|
||||
* @return 方法描述
|
||||
* @throws Exception
|
||||
*/
|
||||
public void getControllerMethodDescription(Log log, OperLog operLog) throws Exception
|
||||
{
|
||||
// 设置action动作
|
||||
operLog.setAction(log.action());
|
||||
// 设置标题
|
||||
operLog.setTitle(log.title());
|
||||
// 设置channel
|
||||
operLog.setChannel(log.channel());
|
||||
// 是否需要保存request,参数和值
|
||||
if (log.isSaveRequestData())
|
||||
{
|
||||
// 获取参数的信息,传入到数据库中。
|
||||
setRequestValue(operLog);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求的参数,放到log中
|
||||
*
|
||||
* @param operLog
|
||||
* @param request
|
||||
*/
|
||||
private void setRequestValue(OperLog operLog)
|
||||
{
|
||||
Map<String, String[]> map = ServletUtils.getRequest().getParameterMap();
|
||||
String params = JSONObject.toJSONString(map);
|
||||
operLog.setOperParam(StringUtils.substring(params, 0, 255));
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否存在注解,如果存在就获取
|
||||
*/
|
||||
private Log getAnnotationLog(JoinPoint joinPoint) throws Exception
|
||||
{
|
||||
Signature signature = joinPoint.getSignature();
|
||||
MethodSignature methodSignature = (MethodSignature) signature;
|
||||
Method method = methodSignature.getMethod();
|
||||
|
||||
if (method != null)
|
||||
{
|
||||
return method.getAnnotation(Log.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package com.ruoyi.framework.aspectj.lang.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 自定义操作日志记录注解
|
||||
*
|
||||
* @author ruoyi
|
||||
*
|
||||
*/
|
||||
@Target({ ElementType.PARAMETER, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Log
|
||||
{
|
||||
/** 模块 */
|
||||
String title() default "";
|
||||
|
||||
/** 功能 */
|
||||
String action() default "";
|
||||
|
||||
/** 渠道 */
|
||||
String channel() default "web";
|
||||
|
||||
/** 是否保存请求的参数 */
|
||||
boolean isSaveRequestData() default true;
|
||||
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import java.util.Properties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import com.google.code.kaptcha.impl.DefaultKaptcha;
|
||||
import com.google.code.kaptcha.util.Config;
|
||||
|
||||
/**
|
||||
* 验证码配置
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
public class CaptchaConfig
|
||||
{
|
||||
@Bean(name = "captchaProducer")
|
||||
public DefaultKaptcha getKaptchaBean()
|
||||
{
|
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("kaptcha.border", "yes");
|
||||
properties.setProperty("kaptcha.border.color", "105,179,90");
|
||||
properties.setProperty("kaptcha.textproducer.font.color", "blue");
|
||||
properties.setProperty("kaptcha.image.width", "160");
|
||||
properties.setProperty("kaptcha.image.height", "60");
|
||||
properties.setProperty("kaptcha.textproducer.font.size", "28");
|
||||
properties.setProperty("kaptcha.session.key", "kaptchaCode");
|
||||
properties.setProperty("kaptcha.textproducer.char.spac", "35");
|
||||
properties.setProperty("kaptcha.textproducer.char.length", "5");
|
||||
properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier");
|
||||
properties.setProperty("kaptcha.noise.color", "white");
|
||||
Config config = new Config(properties);
|
||||
defaultKaptcha.setConfig(config);
|
||||
return defaultKaptcha;
|
||||
}
|
||||
|
||||
@Bean(name = "captchaProducerMath")
|
||||
public DefaultKaptcha getKaptchaBeanMath()
|
||||
{
|
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("kaptcha.border", "yes");
|
||||
properties.setProperty("kaptcha.border.color", "105,179,90");
|
||||
properties.setProperty("kaptcha.textproducer.font.color", "blue");
|
||||
properties.setProperty("kaptcha.image.width", "160");
|
||||
properties.setProperty("kaptcha.image.height", "60");
|
||||
properties.setProperty("kaptcha.textproducer.font.size", "38");
|
||||
properties.setProperty("kaptcha.session.key", "kaptchaCodeMath");
|
||||
properties.setProperty("kaptcha.textproducer.impl", "com.ruoyi.framework.config.KaptchaTextCreator");
|
||||
properties.setProperty("kaptcha.textproducer.char.spac", "5");
|
||||
properties.setProperty("kaptcha.textproducer.char.length", "6");
|
||||
properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier");
|
||||
properties.setProperty("kaptcha.noise.color", "white");
|
||||
properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.NoNoise");
|
||||
properties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.ShadowGimpy");
|
||||
Config config = new Config(properties);
|
||||
defaultKaptcha.setConfig(config);
|
||||
return defaultKaptcha;
|
||||
}
|
||||
}
|
@ -1,159 +0,0 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import com.alibaba.druid.support.http.StatViewServlet;
|
||||
import com.alibaba.druid.support.http.WebStatFilter;
|
||||
|
||||
/**
|
||||
* Druid数据库信息配置加载
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
public class DruidConfig
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(DruidConfig.class);
|
||||
|
||||
@Value("${spring.datasource.url}")
|
||||
private String dbUrl;
|
||||
|
||||
@Value("${spring.datasource.username}")
|
||||
private String username;
|
||||
|
||||
@Value("${spring.datasource.password}")
|
||||
private String password;
|
||||
|
||||
@Value("${spring.datasource.driverClassName}")
|
||||
private String driverClassName;
|
||||
|
||||
@Value("${spring.datasource.initialSize}")
|
||||
private int initialSize;
|
||||
|
||||
@Value("${spring.datasource.minIdle}")
|
||||
private int minIdle;
|
||||
|
||||
@Value("${spring.datasource.maxActive}")
|
||||
private int maxActive;
|
||||
|
||||
@Value("${spring.datasource.maxWait}")
|
||||
private int maxWait;
|
||||
|
||||
@Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
|
||||
private int timeBetweenEvictionRunsMillis;
|
||||
|
||||
@Value("${spring.datasource.minEvictableIdleTimeMillis}")
|
||||
private int minEvictableIdleTimeMillis;
|
||||
|
||||
@Value("${spring.datasource.validationQuery}")
|
||||
private String validationQuery;
|
||||
|
||||
@Value("${spring.datasource.testWhileIdle}")
|
||||
private boolean testWhileIdle;
|
||||
|
||||
@Value("${spring.datasource.testOnBorrow}")
|
||||
private boolean testOnBorrow;
|
||||
|
||||
@Value("${spring.datasource.testOnReturn}")
|
||||
private boolean testOnReturn;
|
||||
|
||||
@Value("${spring.datasource.poolPreparedStatements}")
|
||||
private boolean poolPreparedStatements;
|
||||
|
||||
@Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")
|
||||
private int maxPoolPreparedStatementPerConnectionSize;
|
||||
|
||||
@Value("${spring.datasource.filters}")
|
||||
private String filters;
|
||||
|
||||
@Value("{spring.datasource.connectionProperties}")
|
||||
private String connectionProperties;
|
||||
|
||||
@Bean(initMethod = "init", destroyMethod = "close") /** 声明其为Bean实例 */
|
||||
@Primary /** 在同样的DataSource中,首先使用被标注的DataSource */
|
||||
public DataSource dataSource()
|
||||
{
|
||||
DruidDataSource datasource = new DruidDataSource();
|
||||
|
||||
datasource.setUrl(this.dbUrl);
|
||||
datasource.setUsername(username);
|
||||
datasource.setPassword(password);
|
||||
datasource.setDriverClassName(driverClassName);
|
||||
|
||||
/** configuration */
|
||||
datasource.setInitialSize(initialSize);
|
||||
datasource.setMinIdle(minIdle);
|
||||
datasource.setMaxActive(maxActive);
|
||||
datasource.setMaxWait(maxWait);
|
||||
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
|
||||
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
|
||||
datasource.setValidationQuery(validationQuery);
|
||||
datasource.setTestWhileIdle(testWhileIdle);
|
||||
datasource.setTestOnBorrow(testOnBorrow);
|
||||
datasource.setTestOnReturn(testOnReturn);
|
||||
datasource.setPoolPreparedStatements(poolPreparedStatements);
|
||||
datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
|
||||
try
|
||||
{
|
||||
datasource.setFilters(filters);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
log.error("druid configuration initialization filter", e);
|
||||
}
|
||||
datasource.setConnectionProperties(connectionProperties);
|
||||
|
||||
return datasource;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册一个StatViewServlet 相当于在web.xml中声明了一个servlet
|
||||
*/
|
||||
@Bean
|
||||
public ServletRegistrationBean druidServlet()
|
||||
{
|
||||
ServletRegistrationBean reg = new ServletRegistrationBean();
|
||||
reg.setServlet(new StatViewServlet());
|
||||
reg.addUrlMappings("/monitor/druid/*");
|
||||
/** 白名单 */
|
||||
// reg.addInitParameter("allow", "10.211.61.45,127.0.0.1,123.207.20.136");
|
||||
/** IP黑名单(共同存在时,deny优先于allow) */
|
||||
// reg.addInitParameter("deny", "10.211.61.4");
|
||||
/** 是否能够重置数据 禁用HTML页面上的“Reset All”功能 */
|
||||
reg.addInitParameter("resetEnable", "false");
|
||||
return reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册一个:filterRegistrationBean 相当于在web.xml中声明了一个Filter
|
||||
*/
|
||||
@Bean
|
||||
public FilterRegistrationBean filterRegistrationBean()
|
||||
{
|
||||
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
|
||||
filterRegistrationBean.setFilter(new WebStatFilter());
|
||||
/** 添加过滤规则. */
|
||||
filterRegistrationBean.addUrlPatterns("/*");
|
||||
/** 监控选项滤器 */
|
||||
filterRegistrationBean.addInitParameter("DruidWebStatFilter", "/*");
|
||||
/** 添加不需要忽略的格式信息. */
|
||||
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/monitor/druid/*");
|
||||
/** 配置profileEnable能够监控单个url调用的sql列表 */
|
||||
filterRegistrationBean.addInitParameter("profileEnable", "true");
|
||||
/** 当前的cookie的用户 */
|
||||
filterRegistrationBean.addInitParameter("principalCookieName", "USER_COOKIE");
|
||||
/** 当前的session的用户 */
|
||||
filterRegistrationBean.addInitParameter("principalSessionName", "USER_SESSION");
|
||||
return filterRegistrationBean;
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import com.ruoyi.common.xss.XssFilter;
|
||||
|
||||
/**
|
||||
* Filter配置
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
public class FilterConfig
|
||||
{
|
||||
@Bean
|
||||
public FilterRegistrationBean xssFilterRegistration()
|
||||
{
|
||||
FilterRegistrationBean registration = new FilterRegistrationBean();
|
||||
registration.setDispatcherTypes(DispatcherType.REQUEST);
|
||||
registration.setFilter(new XssFilter());
|
||||
registration.addUrlPatterns("/*");
|
||||
registration.setName("xssFilter");
|
||||
registration.setOrder(Integer.MAX_VALUE);
|
||||
return registration;
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 读取代码生成相关配置
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "gen")
|
||||
public class GenConfig
|
||||
{
|
||||
/** 作者 */
|
||||
public static String author;
|
||||
/** 生成包路径 */
|
||||
public static String packageName;
|
||||
/** 自动去除表前缀,默认是true */
|
||||
public static String autoRemovePre;
|
||||
/** 表前缀(类名不会包含表前缀) */
|
||||
public static String tablePrefix;
|
||||
|
||||
public static String getAuthor()
|
||||
{
|
||||
return author;
|
||||
}
|
||||
|
||||
public static void setAuthor(String author)
|
||||
{
|
||||
GenConfig.author = author;
|
||||
}
|
||||
|
||||
public static String getPackageName()
|
||||
{
|
||||
return packageName;
|
||||
}
|
||||
|
||||
public static void setPackageName(String packageName)
|
||||
{
|
||||
GenConfig.packageName = packageName;
|
||||
}
|
||||
|
||||
public static String getAutoRemovePre()
|
||||
{
|
||||
return autoRemovePre;
|
||||
}
|
||||
|
||||
public static void setAutoRemovePre(String autoRemovePre)
|
||||
{
|
||||
GenConfig.autoRemovePre = autoRemovePre;
|
||||
}
|
||||
|
||||
public static String getTablePrefix()
|
||||
{
|
||||
return tablePrefix;
|
||||
}
|
||||
|
||||
public static void setTablePrefix(String tablePrefix)
|
||||
{
|
||||
GenConfig.tablePrefix = tablePrefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "GenConfig [getClass()=" + getClass() + ", hashCode()=" + hashCode() + ", toString()=" + super.toString()
|
||||
+ "]";
|
||||
}
|
||||
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.LocaleResolver;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
|
||||
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
|
||||
|
||||
/**
|
||||
* 资源文件配置加载
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
@Component
|
||||
public class I18nConfig extends WebMvcConfigurerAdapter
|
||||
{
|
||||
|
||||
@Bean
|
||||
public LocaleResolver localeResolver()
|
||||
{
|
||||
SessionLocaleResolver slr = new SessionLocaleResolver();
|
||||
// 默认语言
|
||||
slr.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
|
||||
return slr;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LocaleChangeInterceptor localeChangeInterceptor()
|
||||
{
|
||||
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
|
||||
// 参数名
|
||||
lci.setParamName("lang");
|
||||
return lci;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry)
|
||||
{
|
||||
registry.addInterceptor(localeChangeInterceptor());
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import java.util.Random;
|
||||
import com.google.code.kaptcha.text.impl.DefaultTextCreator;
|
||||
|
||||
/**
|
||||
* 验证码文本生成器
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class KaptchaTextCreator extends DefaultTextCreator
|
||||
{
|
||||
|
||||
private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");
|
||||
|
||||
@Override
|
||||
public String getText()
|
||||
{
|
||||
Integer result = 0;
|
||||
Random random = new Random();
|
||||
int x = random.nextInt(10);
|
||||
int y = random.nextInt(10);
|
||||
StringBuilder suChinese = new StringBuilder();
|
||||
int randomoperands = (int) Math.round(Math.random() * 2);
|
||||
if (randomoperands == 0)
|
||||
{
|
||||
result = x * y;
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
suChinese.append("*");
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
}
|
||||
else if (randomoperands == 1)
|
||||
{
|
||||
if (!(x == 0) && y % x == 0)
|
||||
{
|
||||
result = y / x;
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
suChinese.append("/");
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = x + y;
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
suChinese.append("+");
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
}
|
||||
}
|
||||
else if (randomoperands == 2)
|
||||
{
|
||||
if (x >= y)
|
||||
{
|
||||
result = x - y;
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
suChinese.append("-");
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = y - x;
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
suChinese.append("-");
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = x + y;
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
suChinese.append("+");
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
}
|
||||
suChinese.append("=?@" + result);
|
||||
return suChinese.toString();
|
||||
}
|
||||
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
/**
|
||||
* 通用配置
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
public class ResourcesConfig extends WebMvcConfigurerAdapter
|
||||
{
|
||||
/**
|
||||
* 首页地址
|
||||
*/
|
||||
@Value("${shiro.user.indexUrl}")
|
||||
private String indexUrl;
|
||||
|
||||
/**
|
||||
* 默认首页的设置,当输入域名是可以自动跳转到默认指定的网页
|
||||
*/
|
||||
@Override
|
||||
public void addViewControllers(ViewControllerRegistry registry)
|
||||
{
|
||||
registry.addViewController("/").setViewName("forward:" + indexUrl);
|
||||
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
|
||||
super.addViewControllers(registry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry)
|
||||
{
|
||||
/** 头像上传路径 */
|
||||
registry.addResourceHandler("/profile/**").addResourceLocations("file:" + RuoYiConfig.getProfile());
|
||||
|
||||
/** swagger配置 */
|
||||
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
|
||||
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 读取项目相关配置
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "ruoyi")
|
||||
public class RuoYiConfig
|
||||
{
|
||||
/** 项目名称 */
|
||||
private String name;
|
||||
/** 版本 */
|
||||
private String version;
|
||||
/** 版权年份 */
|
||||
private String copyrightYear;
|
||||
/** 上传路径 */
|
||||
private static String profile;
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getVersion()
|
||||
{
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version)
|
||||
{
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getCopyrightYear()
|
||||
{
|
||||
return copyrightYear;
|
||||
}
|
||||
|
||||
public void setCopyrightYear(String copyrightYear)
|
||||
{
|
||||
this.copyrightYear = copyrightYear;
|
||||
}
|
||||
|
||||
public static String getProfile()
|
||||
{
|
||||
return profile;
|
||||
}
|
||||
|
||||
public static void setProfile(String profile)
|
||||
{
|
||||
RuoYiConfig.profile = profile;
|
||||
}
|
||||
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* 定时任务配置
|
||||
*
|
||||
* @author ruoyi
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
public class ScheduleConfig
|
||||
{
|
||||
|
||||
@Bean
|
||||
public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource)
|
||||
{
|
||||
SchedulerFactoryBean factory = new SchedulerFactoryBean();
|
||||
factory.setDataSource(dataSource);
|
||||
|
||||
// quartz参数
|
||||
Properties prop = new Properties();
|
||||
prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler");
|
||||
prop.put("org.quartz.scheduler.instanceId", "AUTO");
|
||||
// 线程池配置
|
||||
prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
|
||||
prop.put("org.quartz.threadPool.threadCount", "20");
|
||||
prop.put("org.quartz.threadPool.threadPriority", "5");
|
||||
// JobStore配置
|
||||
prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
|
||||
// 集群配置
|
||||
prop.put("org.quartz.jobStore.isClustered", "true");
|
||||
prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
|
||||
prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
|
||||
|
||||
prop.put("org.quartz.jobStore.misfireThreshold", "12000");
|
||||
prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
|
||||
factory.setQuartzProperties(prop);
|
||||
|
||||
factory.setSchedulerName("RuoyiScheduler");
|
||||
// 延时启动
|
||||
factory.setStartupDelay(1);
|
||||
factory.setApplicationContextSchedulerContextKey("applicationContextKey");
|
||||
// 可选,QuartzScheduler
|
||||
// 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
|
||||
factory.setOverwriteExistingJobs(true);
|
||||
// 设置自动启动,默认为true
|
||||
factory.setAutoStartup(true);
|
||||
|
||||
return factory;
|
||||
}
|
||||
}
|
@ -1,359 +0,0 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
|
||||
import org.apache.shiro.cache.ehcache.EhCacheManager;
|
||||
import org.apache.shiro.codec.Base64;
|
||||
import org.apache.shiro.mgt.SecurityManager;
|
||||
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
|
||||
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
|
||||
import org.apache.shiro.web.mgt.CookieRememberMeManager;
|
||||
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
||||
import org.apache.shiro.web.servlet.SimpleCookie;
|
||||
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.ruoyi.framework.shiro.realm.UserRealm;
|
||||
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
|
||||
import com.ruoyi.framework.shiro.session.OnlineSessionFactory;
|
||||
import com.ruoyi.framework.shiro.web.filter.LogoutFilter;
|
||||
import com.ruoyi.framework.shiro.web.filter.captcha.CaptchaValidateFilter;
|
||||
import com.ruoyi.framework.shiro.web.filter.online.OnlineSessionFilter;
|
||||
import com.ruoyi.framework.shiro.web.filter.sync.SyncOnlineSessionFilter;
|
||||
import com.ruoyi.framework.shiro.web.session.OnlineWebSessionManager;
|
||||
import com.ruoyi.framework.shiro.web.session.SpringSessionValidationScheduler;
|
||||
|
||||
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
|
||||
|
||||
/**
|
||||
* 权限配置加载
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
public class ShiroConfig
|
||||
{
|
||||
public static final String PREMISSION_STRING = "perms[\"{0}\"]";
|
||||
|
||||
// Session超时时间,单位为毫秒(默认30分钟)
|
||||
@Value("${shiro.session.expireTime}")
|
||||
private int expireTime;
|
||||
|
||||
// 相隔多久检查一次session的有效性,单位毫秒,默认就是10分钟
|
||||
@Value("${shiro.session.validationInterval}")
|
||||
private int validationInterval;
|
||||
|
||||
// 验证码开关
|
||||
@Value("${shiro.user.captchaEbabled}")
|
||||
private boolean captchaEbabled;
|
||||
|
||||
// 验证码类型
|
||||
@Value("${shiro.user.captchaType}")
|
||||
private String captchaType;
|
||||
|
||||
// 设置Cookie的域名
|
||||
@Value("${shiro.cookie.domain}")
|
||||
private String domain;
|
||||
|
||||
// 设置cookie的有效访问路径
|
||||
@Value("${shiro.cookie.path}")
|
||||
private String path;
|
||||
|
||||
// 设置HttpOnly属性
|
||||
@Value("${shiro.cookie.httpOnly}")
|
||||
private boolean httpOnly;
|
||||
|
||||
// 设置Cookie的过期时间,秒为单位
|
||||
@Value("${shiro.cookie.maxAge}")
|
||||
private int maxAge;
|
||||
|
||||
// 登录地址
|
||||
@Value("${shiro.user.loginUrl}")
|
||||
private String loginUrl;
|
||||
|
||||
// 权限认证失败地址
|
||||
@Value("${shiro.user.unauthorizedUrl}")
|
||||
private String unauthorizedUrl;
|
||||
|
||||
/**
|
||||
* 缓存管理器 使用Ehcache实现
|
||||
*/
|
||||
@Bean
|
||||
public EhCacheManager getEhCacheManager()
|
||||
{
|
||||
EhCacheManager em = new EhCacheManager();
|
||||
em.setCacheManagerConfigFile("classpath:ehcache/ehcache-shiro.xml");
|
||||
return em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义Realm
|
||||
*/
|
||||
@Bean
|
||||
public UserRealm userRealm(EhCacheManager cacheManager)
|
||||
{
|
||||
UserRealm userRealm = new UserRealm();
|
||||
userRealm.setCacheManager(cacheManager);
|
||||
return userRealm;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义sessionDAO会话
|
||||
*/
|
||||
@Bean
|
||||
public OnlineSessionDAO sessionDAO()
|
||||
{
|
||||
OnlineSessionDAO sessionDAO = new OnlineSessionDAO();
|
||||
return sessionDAO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义sessionFactory会话
|
||||
*/
|
||||
@Bean
|
||||
public OnlineSessionFactory sessionFactory()
|
||||
{
|
||||
OnlineSessionFactory sessionFactory = new OnlineSessionFactory();
|
||||
return sessionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义sessionFactory调度器
|
||||
*/
|
||||
@Bean
|
||||
public SpringSessionValidationScheduler sessionValidationScheduler()
|
||||
{
|
||||
SpringSessionValidationScheduler sessionValidationScheduler = new SpringSessionValidationScheduler();
|
||||
// 相隔多久检查一次session的有效性,单位毫秒,默认就是10分钟
|
||||
sessionValidationScheduler.setSessionValidationInterval(validationInterval * 60 * 1000);
|
||||
// 设置会话验证调度器进行会话验证时的会话管理器
|
||||
sessionValidationScheduler.setSessionManager(sessionValidationManager());
|
||||
return sessionValidationScheduler;
|
||||
}
|
||||
|
||||
/**
|
||||
* 会话管理器
|
||||
*/
|
||||
@Bean
|
||||
public OnlineWebSessionManager sessionValidationManager()
|
||||
{
|
||||
OnlineWebSessionManager manager = new OnlineWebSessionManager();
|
||||
// 加入缓存管理器
|
||||
manager.setCacheManager(getEhCacheManager());
|
||||
// 删除过期的session
|
||||
manager.setDeleteInvalidSessions(true);
|
||||
// 设置全局session超时时间
|
||||
manager.setGlobalSessionTimeout(expireTime * 60 * 1000);
|
||||
// 是否定时检查session
|
||||
manager.setSessionValidationSchedulerEnabled(true);
|
||||
// 自定义SessionDao
|
||||
manager.setSessionDAO(sessionDAO());
|
||||
// 自定义sessionFactory
|
||||
manager.setSessionFactory(sessionFactory());
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 会话管理器
|
||||
*/
|
||||
@Bean
|
||||
public OnlineWebSessionManager sessionManager()
|
||||
{
|
||||
OnlineWebSessionManager manager = new OnlineWebSessionManager();
|
||||
// 加入缓存管理器
|
||||
manager.setCacheManager(getEhCacheManager());
|
||||
// 删除过期的session
|
||||
manager.setDeleteInvalidSessions(true);
|
||||
// 设置全局session超时时间
|
||||
manager.setGlobalSessionTimeout(expireTime * 60 * 1000);
|
||||
// 定义要使用的无效的Session定时调度器
|
||||
manager.setSessionValidationScheduler(sessionValidationScheduler());
|
||||
// 是否定时检查session
|
||||
manager.setSessionValidationSchedulerEnabled(true);
|
||||
// 自定义SessionDao
|
||||
manager.setSessionDAO(sessionDAO());
|
||||
// 自定义sessionFactory
|
||||
manager.setSessionFactory(sessionFactory());
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全管理器
|
||||
*/
|
||||
@Bean
|
||||
public SecurityManager securityManager(UserRealm userRealm)
|
||||
{
|
||||
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
|
||||
// 设置realm.
|
||||
securityManager.setRealm(userRealm);
|
||||
// 记住我
|
||||
securityManager.setRememberMeManager(rememberMeManager());
|
||||
// 注入缓存管理器;
|
||||
securityManager.setCacheManager(getEhCacheManager());
|
||||
// session管理器
|
||||
securityManager.setSessionManager(sessionManager());
|
||||
return securityManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出过滤器
|
||||
*/
|
||||
public LogoutFilter logoutFilter()
|
||||
{
|
||||
LogoutFilter logoutFilter = new LogoutFilter();
|
||||
logoutFilter.setLoginUrl(loginUrl);
|
||||
return logoutFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shiro过滤器配置
|
||||
*/
|
||||
@Bean
|
||||
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager)
|
||||
{
|
||||
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
|
||||
// Shiro的核心安全接口,这个属性是必须的
|
||||
shiroFilterFactoryBean.setSecurityManager(securityManager);
|
||||
// 身份认证失败,则跳转到登录页面的配置
|
||||
shiroFilterFactoryBean.setLoginUrl(loginUrl);
|
||||
// 权限认证失败,则跳转到指定页面
|
||||
shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
|
||||
// Shiro连接约束配置,即过滤链的定义
|
||||
LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
|
||||
// 对静态资源设置匿名访问
|
||||
filterChainDefinitionMap.put("/favicon.ico**", "anon");
|
||||
filterChainDefinitionMap.put("/ruoyi.png**", "anon");
|
||||
filterChainDefinitionMap.put("/css/**", "anon");
|
||||
filterChainDefinitionMap.put("/docs/**", "anon");
|
||||
filterChainDefinitionMap.put("/fonts/**", "anon");
|
||||
filterChainDefinitionMap.put("/img/**", "anon");
|
||||
filterChainDefinitionMap.put("/ajax/**", "anon");
|
||||
filterChainDefinitionMap.put("/js/**", "anon");
|
||||
filterChainDefinitionMap.put("/ruoyi/**", "anon");
|
||||
filterChainDefinitionMap.put("/druid/**", "anon");
|
||||
filterChainDefinitionMap.put("/captcha/captchaImage**", "anon");
|
||||
// 退出 logout地址,shiro去清除session
|
||||
filterChainDefinitionMap.put("/logout", "logout");
|
||||
//强制退出时, 退出logout地址,shiro去清除session,防止出现shiro报没有权限错误。
|
||||
filterChainDefinitionMap.put("/monitor/online/batchForceLogout", "logout");
|
||||
filterChainDefinitionMap.put("/monitor/online/forceLogout/**", "logout");
|
||||
// 不需要拦截的访问
|
||||
filterChainDefinitionMap.put("/login", "anon,captchaValidate");
|
||||
// 系统权限列表
|
||||
// filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());
|
||||
|
||||
Map<String, Filter> filters = new LinkedHashMap<>();
|
||||
filters.put("onlineSession", onlineSessionFilter());
|
||||
filters.put("syncOnlineSession", syncOnlineSessionFilter());
|
||||
filters.put("captchaValidate", captchaValidateFilter());
|
||||
// 注销成功,则跳转到指定页面
|
||||
filters.put("logout", logoutFilter());
|
||||
shiroFilterFactoryBean.setFilters(filters);
|
||||
|
||||
// 所有请求需要认证
|
||||
filterChainDefinitionMap.put("/**", "user");
|
||||
// 系统请求记录当前会话
|
||||
filterChainDefinitionMap.put("/main", "onlineSession,syncOnlineSession");
|
||||
filterChainDefinitionMap.put("/system/**", "onlineSession,syncOnlineSession");
|
||||
filterChainDefinitionMap.put("/monitor/**", "onlineSession,syncOnlineSession");
|
||||
filterChainDefinitionMap.put("/tool/**", "onlineSession,syncOnlineSession");
|
||||
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
|
||||
|
||||
return shiroFilterFactoryBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义在线用户处理过滤器
|
||||
*/
|
||||
@Bean
|
||||
public OnlineSessionFilter onlineSessionFilter()
|
||||
{
|
||||
OnlineSessionFilter onlineSessionFilter = new OnlineSessionFilter();
|
||||
onlineSessionFilter.setLoginUrl(loginUrl);
|
||||
return onlineSessionFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义在线用户同步过滤器
|
||||
*/
|
||||
@Bean
|
||||
public SyncOnlineSessionFilter syncOnlineSessionFilter()
|
||||
{
|
||||
SyncOnlineSessionFilter syncOnlineSessionFilter = new SyncOnlineSessionFilter();
|
||||
return syncOnlineSessionFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义验证码过滤器
|
||||
*/
|
||||
@Bean
|
||||
public CaptchaValidateFilter captchaValidateFilter()
|
||||
{
|
||||
CaptchaValidateFilter captchaValidateFilter = new CaptchaValidateFilter();
|
||||
captchaValidateFilter.setCaptchaEbabled(captchaEbabled);
|
||||
captchaValidateFilter.setCaptchaType(captchaType);
|
||||
return captchaValidateFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* cookie 属性设置
|
||||
*/
|
||||
public SimpleCookie rememberMeCookie()
|
||||
{
|
||||
SimpleCookie cookie = new SimpleCookie("rememberMe");
|
||||
cookie.setDomain(domain);
|
||||
cookie.setPath(path);
|
||||
cookie.setHttpOnly(httpOnly);
|
||||
cookie.setMaxAge(maxAge * 24 * 60 * 60);
|
||||
return cookie;
|
||||
}
|
||||
|
||||
/**
|
||||
* 记住我
|
||||
*/
|
||||
public CookieRememberMeManager rememberMeManager()
|
||||
{
|
||||
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
|
||||
cookieRememberMeManager.setCookie(rememberMeCookie());
|
||||
cookieRememberMeManager.setCipherKey(Base64.decode("fCq+/xW488hMTCD+cmJ3aQ=="));
|
||||
return cookieRememberMeManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启Shiro代理
|
||||
*/
|
||||
@Bean
|
||||
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator()
|
||||
{
|
||||
DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
|
||||
proxyCreator.setProxyTargetClass(true);
|
||||
return proxyCreator;
|
||||
}
|
||||
|
||||
/**
|
||||
* thymeleaf模板引擎和shiro框架的整合
|
||||
*/
|
||||
@Bean
|
||||
public ShiroDialect shiroDialect()
|
||||
{
|
||||
return new ShiroDialect();
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启Shiro注解通知器
|
||||
*/
|
||||
@Bean
|
||||
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
|
||||
@Qualifier("securityManager") SecurityManager securityManager)
|
||||
{
|
||||
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
|
||||
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
|
||||
return authorizationAttributeSourceAdvisor;
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
import springfox.documentation.service.ApiInfo;
|
||||
import springfox.documentation.service.Contact;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
|
||||
/**
|
||||
* Swagger2的接口配置
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
@EnableSwagger2
|
||||
public class SwaggerConfig
|
||||
{
|
||||
/** 系统基础配置 */
|
||||
@Autowired
|
||||
private RuoYiConfig ruoYiConfig;
|
||||
|
||||
/**
|
||||
* 创建API
|
||||
*/
|
||||
@Bean
|
||||
public Docket createRestApi()
|
||||
{
|
||||
return new Docket(DocumentationType.SWAGGER_2)
|
||||
// 详细定制
|
||||
.apiInfo(apiInfo())
|
||||
.select()
|
||||
// 指定当前包路径
|
||||
.apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger"))
|
||||
// 扫描所有 .apis(RequestHandlerSelectors.any())
|
||||
.paths(PathSelectors.any())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加摘要信息
|
||||
*/
|
||||
private ApiInfo apiInfo()
|
||||
{
|
||||
// 用ApiInfoBuilder进行定制
|
||||
return new ApiInfoBuilder()
|
||||
.title("标题:若依管理系统_接口文档")
|
||||
.description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
|
||||
.contact(new Contact(ruoYiConfig.getName(), null, null))
|
||||
.version("版本号:" + ruoYiConfig.getVersion())
|
||||
.build();
|
||||
}
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
package com.ruoyi.framework.shiro.realm;
|
||||
|
||||
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.ExcessiveAttemptsException;
|
||||
import org.apache.shiro.authc.IncorrectCredentialsException;
|
||||
import org.apache.shiro.authc.LockedAccountException;
|
||||
import org.apache.shiro.authc.SimpleAuthenticationInfo;
|
||||
import org.apache.shiro.authc.UnknownAccountException;
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
import org.apache.shiro.authz.AuthorizationInfo;
|
||||
import org.apache.shiro.authz.SimpleAuthorizationInfo;
|
||||
import org.apache.shiro.realm.AuthorizingRealm;
|
||||
import org.apache.shiro.subject.PrincipalCollection;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.ruoyi.common.exception.user.CaptchaException;
|
||||
import com.ruoyi.common.exception.user.RoleBlockedException;
|
||||
import com.ruoyi.common.exception.user.UserBlockedException;
|
||||
import com.ruoyi.common.exception.user.UserNotExistsException;
|
||||
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
|
||||
import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException;
|
||||
import com.ruoyi.common.utils.security.ShiroUtils;
|
||||
import com.ruoyi.framework.shiro.service.LoginService;
|
||||
import com.ruoyi.project.system.menu.service.IMenuService;
|
||||
import com.ruoyi.project.system.role.service.IRoleService;
|
||||
import com.ruoyi.project.system.user.domain.User;
|
||||
|
||||
/**
|
||||
* 自定义Realm 处理登录 权限
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class UserRealm extends AuthorizingRealm
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(UserRealm.class);
|
||||
|
||||
@Autowired
|
||||
private IMenuService menuService;
|
||||
|
||||
@Autowired
|
||||
private IRoleService roleService;
|
||||
|
||||
@Autowired
|
||||
private LoginService loginService;
|
||||
|
||||
/**
|
||||
* 授权
|
||||
*/
|
||||
@Override
|
||||
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0)
|
||||
{
|
||||
Long userId = ShiroUtils.getUserId();
|
||||
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
|
||||
// 角色加入AuthorizationInfo认证对象
|
||||
info.setRoles(roleService.selectRoleKeys(userId));
|
||||
// 权限加入AuthorizationInfo认证对象
|
||||
info.setStringPermissions(menuService.selectPermsByUserId(userId));
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录认证
|
||||
*/
|
||||
@Override
|
||||
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException
|
||||
{
|
||||
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
|
||||
String username = upToken.getUsername();
|
||||
String password = "";
|
||||
if (upToken.getPassword() != null)
|
||||
{
|
||||
password = new String(upToken.getPassword());
|
||||
}
|
||||
|
||||
User user = null;
|
||||
try
|
||||
{
|
||||
user = loginService.login(username, password);
|
||||
}
|
||||
catch (CaptchaException e)
|
||||
{
|
||||
throw new AuthenticationException(e.getMessage(), e);
|
||||
}
|
||||
catch (UserNotExistsException e)
|
||||
{
|
||||
throw new UnknownAccountException(e.getMessage(), e);
|
||||
}
|
||||
catch (UserPasswordNotMatchException e)
|
||||
{
|
||||
throw new IncorrectCredentialsException(e.getMessage(), e);
|
||||
}
|
||||
catch (UserPasswordRetryLimitExceedException e)
|
||||
{
|
||||
throw new ExcessiveAttemptsException(e.getMessage(), e);
|
||||
}
|
||||
catch (UserBlockedException e)
|
||||
{
|
||||
throw new LockedAccountException(e.getMessage(), e);
|
||||
}
|
||||
catch (RoleBlockedException e)
|
||||
{
|
||||
throw new LockedAccountException(e.getMessage(), e);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.info("对用户[" + username + "]进行登录验证..验证未通过{}", e.getMessage());
|
||||
throw new AuthenticationException(e.getMessage(), e);
|
||||
}
|
||||
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理缓存权限
|
||||
*/
|
||||
public void clearCachedAuthorizationInfo()
|
||||
{
|
||||
this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
|
||||
}
|
||||
|
||||
}
|
@ -1,128 +0,0 @@
|
||||
package com.ruoyi.framework.shiro.service;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.constant.ShiroConstants;
|
||||
import com.ruoyi.common.constant.UserConstants;
|
||||
import com.ruoyi.common.exception.user.CaptchaException;
|
||||
import com.ruoyi.common.exception.user.UserBlockedException;
|
||||
import com.ruoyi.common.exception.user.UserNotExistsException;
|
||||
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.MessageUtils;
|
||||
import com.ruoyi.common.utils.ServletUtils;
|
||||
import com.ruoyi.common.utils.SystemLogUtils;
|
||||
import com.ruoyi.common.utils.security.ShiroUtils;
|
||||
import com.ruoyi.project.system.user.domain.User;
|
||||
import com.ruoyi.project.system.user.domain.UserStatus;
|
||||
import com.ruoyi.project.system.user.service.IUserService;
|
||||
|
||||
/**
|
||||
* 登录校验方法
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class LoginService
|
||||
{
|
||||
@Autowired
|
||||
private PasswordService passwordService;
|
||||
|
||||
@Autowired
|
||||
private IUserService userService;
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
public User login(String username, String password)
|
||||
{
|
||||
// 验证码校验
|
||||
if (!StringUtils.isEmpty(ServletUtils.getStrAttribute(ShiroConstants.CURRENT_CAPTCHA)))
|
||||
{
|
||||
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"));
|
||||
throw new CaptchaException();
|
||||
}
|
||||
// 用户名或密码为空 错误
|
||||
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
|
||||
{
|
||||
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null"));
|
||||
throw new UserNotExistsException();
|
||||
}
|
||||
// 密码如果不在指定范围内 错误
|
||||
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|
||||
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH)
|
||||
{
|
||||
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"));
|
||||
throw new UserPasswordNotMatchException();
|
||||
}
|
||||
|
||||
// 用户名不在指定范围内 错误
|
||||
if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|
||||
|| username.length() > UserConstants.USERNAME_MAX_LENGTH)
|
||||
{
|
||||
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"));
|
||||
throw new UserPasswordNotMatchException();
|
||||
}
|
||||
|
||||
// 查询用户信息
|
||||
User user = userService.selectUserByLoginName(username);
|
||||
|
||||
if (user == null && maybeMobilePhoneNumber(username))
|
||||
{
|
||||
user = userService.selectUserByPhoneNumber(username);
|
||||
}
|
||||
|
||||
if (user == null && maybeEmail(username))
|
||||
{
|
||||
user = userService.selectUserByEmail(username);
|
||||
}
|
||||
|
||||
if (user == null || UserStatus.DELETED.getCode() == user.getStatus())
|
||||
{
|
||||
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.not.exists"));
|
||||
throw new UserNotExistsException();
|
||||
}
|
||||
|
||||
passwordService.validate(user, password);
|
||||
|
||||
if (UserStatus.DISABLE.getCode() == user.getStatus())
|
||||
{
|
||||
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.blocked", user.getRemark()));
|
||||
throw new UserBlockedException(user.getRemark());
|
||||
}
|
||||
SystemLogUtils.log(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
|
||||
recordLoginInfo(user);
|
||||
return user;
|
||||
}
|
||||
|
||||
private boolean maybeEmail(String username)
|
||||
{
|
||||
if (!username.matches(UserConstants.EMAIL_PATTERN))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean maybeMobilePhoneNumber(String username)
|
||||
{
|
||||
if (!username.matches(UserConstants.MOBILE_PHONE_NUMBER_PATTERN))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录登录信息
|
||||
*/
|
||||
public void recordLoginInfo(User user)
|
||||
{
|
||||
user.setLoginIp(ShiroUtils.getIp());
|
||||
user.setLoginDate(DateUtils.getNowDate());
|
||||
userService.updateUser(user);
|
||||
}
|
||||
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
package com.ruoyi.framework.shiro.service;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import javax.annotation.PostConstruct;
|
||||
import org.apache.shiro.cache.Cache;
|
||||
import org.apache.shiro.cache.CacheManager;
|
||||
import org.apache.shiro.crypto.hash.Md5Hash;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
|
||||
import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException;
|
||||
import com.ruoyi.common.utils.MessageUtils;
|
||||
import com.ruoyi.common.utils.SystemLogUtils;
|
||||
import com.ruoyi.project.system.user.domain.User;
|
||||
|
||||
/**
|
||||
* 登录密码方法
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class PasswordService
|
||||
{
|
||||
|
||||
@Autowired
|
||||
private CacheManager cacheManager;
|
||||
|
||||
private Cache<String, AtomicInteger> loginRecordCache;
|
||||
|
||||
@Value(value = "${user.password.maxRetryCount}")
|
||||
private String maxRetryCount;
|
||||
|
||||
@PostConstruct
|
||||
public void init()
|
||||
{
|
||||
loginRecordCache = cacheManager.getCache("loginRecordCache");
|
||||
}
|
||||
|
||||
public void validate(User user, String password)
|
||||
{
|
||||
String loginName = user.getLoginName();
|
||||
|
||||
AtomicInteger retryCount = loginRecordCache.get(loginName);
|
||||
|
||||
if (retryCount == null)
|
||||
{
|
||||
retryCount = new AtomicInteger(0);
|
||||
loginRecordCache.put(loginName, retryCount);
|
||||
}
|
||||
if (retryCount.incrementAndGet() > Integer.valueOf(maxRetryCount).intValue())
|
||||
{
|
||||
SystemLogUtils.log(loginName, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount));
|
||||
throw new UserPasswordRetryLimitExceedException(Integer.valueOf(maxRetryCount).intValue());
|
||||
}
|
||||
|
||||
if (!matches(user, password))
|
||||
{
|
||||
SystemLogUtils.log(loginName, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.count", retryCount, password));
|
||||
loginRecordCache.put(loginName, retryCount);
|
||||
throw new UserPasswordNotMatchException();
|
||||
}
|
||||
else
|
||||
{
|
||||
clearLoginRecordCache(loginName);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean matches(User user, String newPassword)
|
||||
{
|
||||
return user.getPassword().equals(encryptPassword(user.getLoginName(), newPassword, user.getSalt()));
|
||||
}
|
||||
|
||||
public void clearLoginRecordCache(String username)
|
||||
{
|
||||
loginRecordCache.remove(username);
|
||||
}
|
||||
|
||||
public String encryptPassword(String username, String password, String salt)
|
||||
{
|
||||
return new Md5Hash(username + password + salt).toHex().toString();
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
//System.out.println(new PasswordService().encryptPassword("admin", "admin123", "111111"));
|
||||
//System.out.println(new PasswordService().encryptPassword("ry", "admin123", "222222"));
|
||||
System.out.println(new PasswordService().encryptPassword("ly", "admin123", "123456"));
|
||||
System.out.println(new PasswordService().encryptPassword("ce", "admin123", "123456"));
|
||||
System.out.println(new PasswordService().encryptPassword("zs", "admin123", "123456"));
|
||||
System.out.println(new PasswordService().encryptPassword("ls", "admin123", "123456"));
|
||||
System.out.println(new PasswordService().encryptPassword("ww", "admin123", "123456"));
|
||||
System.out.println(new PasswordService().encryptPassword("zl", "admin123", "123456"));
|
||||
System.out.println(new PasswordService().encryptPassword("sq", "admin123", "123456"));
|
||||
System.out.println(new PasswordService().encryptPassword("zb", "admin123", "123456"));
|
||||
System.out.println(new PasswordService().encryptPassword("wj", "admin123", "123456"));
|
||||
System.out.println(new PasswordService().encryptPassword("ys", "admin123", "123456"));
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
package com.ruoyi.framework.shiro.service;
|
||||
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* RuoYi首创 js调用 thymeleaf 实现按钮权限可见性
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class PermissionService
|
||||
{
|
||||
public String hasPermi(String permission)
|
||||
{
|
||||
return isPermittedOperator(permission) ? "" : "hidden";
|
||||
}
|
||||
|
||||
private boolean isPermittedOperator(String permission)
|
||||
{
|
||||
if (SecurityUtils.getSubject().isPermitted(permission))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
package com.ruoyi.framework.shiro.session;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import org.apache.shiro.session.Session;
|
||||
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import com.ruoyi.project.monitor.online.domain.OnlineSession;
|
||||
import com.ruoyi.project.monitor.online.domain.UserOnline;
|
||||
import com.ruoyi.project.monitor.online.service.IUserOnlineService;
|
||||
|
||||
/**
|
||||
* 针对自定义的ShiroSession的db操作
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class OnlineSessionDAO extends EnterpriseCacheSessionDAO
|
||||
{
|
||||
/**
|
||||
* 同步session到数据库的周期 单位为毫秒(默认1分钟)
|
||||
*/
|
||||
@Value("${shiro.session.dbSyncPeriod}")
|
||||
private int dbSyncPeriod;
|
||||
|
||||
/**
|
||||
* 上次同步数据库的时间戳
|
||||
*/
|
||||
private static final String LAST_SYNC_DB_TIMESTAMP = OnlineSessionDAO.class.getName() + "LAST_SYNC_DB_TIMESTAMP";
|
||||
|
||||
@Autowired
|
||||
private IUserOnlineService onlineService;
|
||||
|
||||
@Autowired
|
||||
private OnlineSessionFactory onlineSessionFactory;
|
||||
|
||||
public OnlineSessionDAO()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public OnlineSessionDAO(long expireTime)
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据会话ID获取会话
|
||||
*
|
||||
* @param sessionId 会话ID
|
||||
* @return ShiroSession
|
||||
*/
|
||||
@Override
|
||||
protected Session doReadSession(Serializable sessionId)
|
||||
{
|
||||
UserOnline userOnline = onlineService.selectOnlineById(String.valueOf(sessionId));
|
||||
if (userOnline == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return onlineSessionFactory.createSession(userOnline);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新会话;如更新会话最后访问时间/停止会话/设置超时时间/设置移除属性等会调用
|
||||
*/
|
||||
public void syncToDb(OnlineSession onlineSession)
|
||||
{
|
||||
Date lastSyncTimestamp = (Date) onlineSession.getAttribute(LAST_SYNC_DB_TIMESTAMP);
|
||||
if (lastSyncTimestamp != null)
|
||||
{
|
||||
boolean needSync = true;
|
||||
long deltaTime = onlineSession.getLastAccessTime().getTime() - lastSyncTimestamp.getTime();
|
||||
if (deltaTime < dbSyncPeriod * 60 * 1000)
|
||||
{
|
||||
// 时间差不足 无需同步
|
||||
needSync = false;
|
||||
}
|
||||
boolean isGuest = onlineSession.getUserId() == null || onlineSession.getUserId() == 0L;
|
||||
|
||||
// session 数据变更了 同步
|
||||
if (isGuest == false && onlineSession.isAttributeChanged())
|
||||
{
|
||||
needSync = true;
|
||||
}
|
||||
|
||||
if (needSync == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
onlineSession.setAttribute(LAST_SYNC_DB_TIMESTAMP, onlineSession.getLastAccessTime());
|
||||
// 更新完后 重置标识
|
||||
if (onlineSession.isAttributeChanged())
|
||||
{
|
||||
onlineSession.resetAttributeChanged();
|
||||
}
|
||||
onlineService.saveOnline(UserOnline.fromOnlineSession(onlineSession));
|
||||
}
|
||||
|
||||
/**
|
||||
* 当会话过期/停止(如用户退出时)属性等会调用
|
||||
*/
|
||||
@Override
|
||||
protected void doDelete(Session session)
|
||||
{
|
||||
OnlineSession onlineSession = (OnlineSession) session;
|
||||
if (null == onlineSession)
|
||||
{
|
||||
return;
|
||||
}
|
||||
onlineSession.setStatus(OnlineSession.OnlineStatus.off_line);
|
||||
onlineService.deleteOnlineById(String.valueOf(onlineSession.getId()));
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
package com.ruoyi.framework.shiro.session;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.apache.shiro.session.Session;
|
||||
import org.apache.shiro.session.mgt.SessionContext;
|
||||
import org.apache.shiro.session.mgt.SessionFactory;
|
||||
import org.apache.shiro.web.session.mgt.WebSessionContext;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.ruoyi.common.utils.ServletUtils;
|
||||
import com.ruoyi.common.utils.IpUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.project.monitor.online.domain.OnlineSession;
|
||||
import com.ruoyi.project.monitor.online.domain.UserOnline;
|
||||
import eu.bitwalker.useragentutils.UserAgent;
|
||||
|
||||
/**
|
||||
* 自定义sessionFactory会话
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class OnlineSessionFactory implements SessionFactory
|
||||
{
|
||||
public Session createSession(UserOnline userOnline)
|
||||
{
|
||||
OnlineSession onlineSession = userOnline.getSession();
|
||||
if (StringUtils.isNotNull(onlineSession) && onlineSession.getId() == null)
|
||||
{
|
||||
onlineSession.setId(userOnline.getSessionId());
|
||||
}
|
||||
return userOnline.getSession();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Session createSession(SessionContext initData)
|
||||
{
|
||||
OnlineSession session = new OnlineSession();
|
||||
if (initData != null && initData instanceof WebSessionContext)
|
||||
{
|
||||
WebSessionContext sessionContext = (WebSessionContext) initData;
|
||||
HttpServletRequest request = (HttpServletRequest) sessionContext.getServletRequest();
|
||||
if (request != null)
|
||||
{
|
||||
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
|
||||
// 获取客户端操作系统
|
||||
String os = userAgent.getOperatingSystem().getName();
|
||||
// 获取客户端浏览器
|
||||
String browser = userAgent.getBrowser().getName();
|
||||
session.setHost(IpUtils.getIpAddr(request));
|
||||
session.setBrowser(browser);
|
||||
session.setOs(os);
|
||||
}
|
||||
}
|
||||
return session;
|
||||
}
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
package com.ruoyi.framework.shiro.web.filter;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import org.apache.shiro.session.SessionException;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.utils.MessageUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.SystemLogUtils;
|
||||
import com.ruoyi.common.utils.security.ShiroUtils;
|
||||
import com.ruoyi.project.system.user.domain.User;
|
||||
|
||||
/**
|
||||
* 退出过滤器
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(LogoutFilter.class);
|
||||
|
||||
/**
|
||||
* 退出后重定向的地址
|
||||
*/
|
||||
private String loginUrl;
|
||||
|
||||
public String getLoginUrl()
|
||||
{
|
||||
return loginUrl;
|
||||
}
|
||||
|
||||
public void setLoginUrl(String loginUrl)
|
||||
{
|
||||
this.loginUrl = loginUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
Subject subject = getSubject(request, response);
|
||||
String redirectUrl = getRedirectUrl(request, response, subject);
|
||||
try
|
||||
{
|
||||
User user = (User) ShiroUtils.getSubjct().getPrincipal();
|
||||
if (StringUtils.isNotNull(user))
|
||||
{
|
||||
String loginName = user.getLoginName();
|
||||
// 记录用户退出日志
|
||||
SystemLogUtils.log(loginName, Constants.LOGOUT, MessageUtils.message("user.logout.success"));
|
||||
}
|
||||
// 退出登录
|
||||
subject.logout();
|
||||
}
|
||||
catch (SessionException ise)
|
||||
{
|
||||
log.error("logout fail.", ise);
|
||||
}
|
||||
issueRedirect(request, response, redirectUrl);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.debug("Encountered session exception during logout. This can generally safely be ignored.", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出跳转URL
|
||||
*/
|
||||
@Override
|
||||
protected String getRedirectUrl(ServletRequest request, ServletResponse response, Subject subject)
|
||||
{
|
||||
String url = getLoginUrl();
|
||||
if (StringUtils.isNotEmpty(url))
|
||||
{
|
||||
return url;
|
||||
}
|
||||
return super.getRedirectUrl(request, response, subject);
|
||||
}
|
||||
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
package com.ruoyi.framework.shiro.web.filter.captcha;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.apache.shiro.web.filter.AccessControlFilter;
|
||||
import com.google.code.kaptcha.Constants;
|
||||
import com.ruoyi.common.constant.ShiroConstants;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.security.ShiroUtils;
|
||||
|
||||
/**
|
||||
* 验证码过滤器
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class CaptchaValidateFilter extends AccessControlFilter
|
||||
{
|
||||
|
||||
/**
|
||||
* 是否开启验证码
|
||||
*/
|
||||
private boolean captchaEbabled = true;
|
||||
|
||||
/**
|
||||
* 验证码类型
|
||||
*/
|
||||
private String captchaType = "math";
|
||||
|
||||
public void setCaptchaEbabled(boolean captchaEbabled)
|
||||
{
|
||||
this.captchaEbabled = captchaEbabled;
|
||||
}
|
||||
|
||||
public void setCaptchaType(String captchaType)
|
||||
{
|
||||
this.captchaType = captchaType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception
|
||||
{
|
||||
request.setAttribute(ShiroConstants.CURRENT_EBABLED, captchaEbabled);
|
||||
request.setAttribute(ShiroConstants.CURRENT_TYPE, captchaType);
|
||||
return super.onPreHandle(request, response, mappedValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
|
||||
throws Exception
|
||||
{
|
||||
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
|
||||
// 验证码禁用 或不是表单提交 允许访问
|
||||
if (captchaEbabled == false || !"post".equals(httpServletRequest.getMethod().toLowerCase()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return validateResponse(httpServletRequest, httpServletRequest.getParameter(ShiroConstants.CURRENT_VALIDATECODE));
|
||||
}
|
||||
|
||||
public boolean validateResponse(HttpServletRequest request, String validateCode)
|
||||
{
|
||||
Object obj = ShiroUtils.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
|
||||
String code = String.valueOf(obj != null ? obj : "");
|
||||
if (StringUtils.isEmpty(validateCode) || !validateCode.equalsIgnoreCase(code))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception
|
||||
{
|
||||
request.setAttribute(ShiroConstants.CURRENT_CAPTCHA, ShiroConstants.CAPTCHA_ERROR);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
package com.ruoyi.framework.shiro.web.filter.online;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import org.apache.shiro.session.Session;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.apache.shiro.web.filter.AccessControlFilter;
|
||||
import org.apache.shiro.web.util.WebUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
import com.ruoyi.common.constant.ShiroConstants;
|
||||
import com.ruoyi.common.utils.security.ShiroUtils;
|
||||
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
|
||||
import com.ruoyi.project.monitor.online.domain.OnlineSession;
|
||||
import com.ruoyi.project.system.user.domain.User;
|
||||
|
||||
/**
|
||||
* 自定义访问控制
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class OnlineSessionFilter extends AccessControlFilter
|
||||
{
|
||||
|
||||
/**
|
||||
* 强制退出后重定向的地址
|
||||
*/
|
||||
@Value("${shiro.user.loginUrl}")
|
||||
private String loginUrl;
|
||||
|
||||
@Autowired
|
||||
private OnlineSessionDAO onlineSessionDAO;
|
||||
|
||||
/**
|
||||
* 表示是否允许访问;mappedValue就是[urls]配置中拦截器参数部分,如果允许访问返回true,否则false;
|
||||
*/
|
||||
@Override
|
||||
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
|
||||
throws Exception
|
||||
{
|
||||
Subject subject = getSubject(request, response);
|
||||
if (subject == null || subject.getSession() == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Session session = onlineSessionDAO.readSession(subject.getSession().getId());
|
||||
if (session != null && session instanceof OnlineSession)
|
||||
{
|
||||
OnlineSession onlineSession = (OnlineSession) session;
|
||||
request.setAttribute(ShiroConstants.ONLINE_SESSION, onlineSession);
|
||||
// 把user对象设置进去
|
||||
boolean isGuest = onlineSession.getUserId() == null || onlineSession.getUserId() == 0L;
|
||||
if (isGuest == true)
|
||||
{
|
||||
User user = ShiroUtils.getUser();
|
||||
if (user != null)
|
||||
{
|
||||
onlineSession.setUserId(user.getUserId());
|
||||
onlineSession.setLoginName(user.getLoginName());
|
||||
onlineSession.setDeptName(user.getDept().getDeptName());
|
||||
onlineSession.markAttributeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
if (onlineSession.getStatus() == OnlineSession.OnlineStatus.off_line)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 表示当访问拒绝时是否已经处理了;如果返回true表示需要继续处理;如果返回false表示该拦截器实例已经处理了,将直接返回即可。
|
||||
*/
|
||||
@Override
|
||||
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception
|
||||
{
|
||||
Subject subject = getSubject(request, response);
|
||||
if (subject != null)
|
||||
{
|
||||
subject.logout();
|
||||
}
|
||||
saveRequestAndRedirectToLogin(request, response);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 跳转到登录页
|
||||
@Override
|
||||
protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException
|
||||
{
|
||||
WebUtils.issueRedirect(request, response, loginUrl);
|
||||
}
|
||||
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package com.ruoyi.framework.shiro.web.filter.sync;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import org.apache.shiro.web.filter.PathMatchingFilter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.ruoyi.common.constant.ShiroConstants;
|
||||
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
|
||||
import com.ruoyi.project.monitor.online.domain.OnlineSession;
|
||||
|
||||
/**
|
||||
* 同步Session数据到Db
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class SyncOnlineSessionFilter extends PathMatchingFilter
|
||||
{
|
||||
@Autowired
|
||||
private OnlineSessionDAO onlineSessionDAO;
|
||||
|
||||
/**
|
||||
* 同步会话数据到DB 一次请求最多同步一次 防止过多处理 需要放到Shiro过滤器之前
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception
|
||||
{
|
||||
OnlineSession session = (OnlineSession) request.getAttribute(ShiroConstants.ONLINE_SESSION);
|
||||
// 如果session stop了 也不同步
|
||||
// session停止时间,如果stopTimestamp不为null,则代表已停止
|
||||
if (session != null && session.getUserId() != null && session.getStopTimestamp() == null)
|
||||
{
|
||||
onlineSessionDAO.syncToDb(session);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,155 +0,0 @@
|
||||
package com.ruoyi.framework.shiro.web.session;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.apache.shiro.session.ExpiredSessionException;
|
||||
import org.apache.shiro.session.InvalidSessionException;
|
||||
import org.apache.shiro.session.Session;
|
||||
import org.apache.shiro.session.mgt.DefaultSessionKey;
|
||||
import org.apache.shiro.session.mgt.SessionKey;
|
||||
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import com.ruoyi.common.constant.ShiroConstants;
|
||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||
import com.ruoyi.project.monitor.online.domain.OnlineSession;
|
||||
import com.ruoyi.project.monitor.online.domain.UserOnline;
|
||||
import com.ruoyi.project.monitor.online.service.UserOnlineServiceImpl;
|
||||
|
||||
/**
|
||||
* 主要是在此如果会话的属性修改了 就标识下其修改了 然后方便 OnlineSessionDao同步
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class OnlineWebSessionManager extends DefaultWebSessionManager
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(OnlineWebSessionManager.class);
|
||||
|
||||
@Override
|
||||
public void setAttribute(SessionKey sessionKey, Object attributeKey, Object value) throws InvalidSessionException
|
||||
{
|
||||
super.setAttribute(sessionKey, attributeKey, value);
|
||||
if (value != null && needMarkAttributeChanged(attributeKey))
|
||||
{
|
||||
OnlineSession s = (OnlineSession) doGetSession(sessionKey);
|
||||
s.markAttributeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean needMarkAttributeChanged(Object attributeKey)
|
||||
{
|
||||
if (attributeKey == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
String attributeKeyStr = attributeKey.toString();
|
||||
// 优化 flash属性没必要持久化
|
||||
if (attributeKeyStr.startsWith("org.springframework"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (attributeKeyStr.startsWith("javax.servlet"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (attributeKeyStr.equals(ShiroConstants.CURRENT_USERNAME))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object removeAttribute(SessionKey sessionKey, Object attributeKey) throws InvalidSessionException
|
||||
{
|
||||
Object removed = super.removeAttribute(sessionKey, attributeKey);
|
||||
if (removed != null)
|
||||
{
|
||||
OnlineSession s = (OnlineSession) doGetSession(sessionKey);
|
||||
s.markAttributeChanged();
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证session是否有效 用于删除过期session
|
||||
*/
|
||||
@Override
|
||||
public void validateSessions()
|
||||
{
|
||||
if (log.isInfoEnabled())
|
||||
{
|
||||
log.info("invalidation sessions...");
|
||||
}
|
||||
|
||||
int invalidCount = 0;
|
||||
|
||||
int timeout = (int) this.getGlobalSessionTimeout();
|
||||
Date expiredDate = DateUtils.addMilliseconds(new Date(), 0 - timeout);
|
||||
UserOnlineServiceImpl userOnlineService = SpringUtils.getBean(UserOnlineServiceImpl.class);
|
||||
List<UserOnline> userOnlineList = userOnlineService.selectOnlineByExpired(expiredDate);
|
||||
// 批量过期删除
|
||||
List<String> needOfflineIdList = new ArrayList<String>();
|
||||
for (UserOnline userOnline : userOnlineList)
|
||||
{
|
||||
try
|
||||
{
|
||||
SessionKey key = new DefaultSessionKey(userOnline.getSessionId());
|
||||
Session session = retrieveSession(key);
|
||||
if (session != null)
|
||||
{
|
||||
throw new InvalidSessionException();
|
||||
}
|
||||
}
|
||||
catch (InvalidSessionException e)
|
||||
{
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
boolean expired = (e instanceof ExpiredSessionException);
|
||||
String msg = "Invalidated session with id [" + userOnline.getSessionId() + "]"
|
||||
+ (expired ? " (expired)" : " (stopped)");
|
||||
log.debug(msg);
|
||||
}
|
||||
invalidCount++;
|
||||
needOfflineIdList.add(userOnline.getSessionId());
|
||||
}
|
||||
|
||||
}
|
||||
if (needOfflineIdList.size() > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
userOnlineService.batchDeleteOnline(needOfflineIdList);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("batch delete db session error.", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (log.isInfoEnabled())
|
||||
{
|
||||
String msg = "Finished invalidation session.";
|
||||
if (invalidCount > 0)
|
||||
{
|
||||
msg += " [" + invalidCount + "] sessions were stopped.";
|
||||
}
|
||||
else
|
||||
{
|
||||
msg += " No sessions were stopped.";
|
||||
}
|
||||
log.info(msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Session> getActiveSessions()
|
||||
{
|
||||
throw new UnsupportedOperationException("getActiveSessions method not supported");
|
||||
}
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
package com.ruoyi.framework.shiro.web.session;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.apache.shiro.session.mgt.DefaultSessionManager;
|
||||
import org.apache.shiro.session.mgt.SessionValidationScheduler;
|
||||
import org.apache.shiro.session.mgt.ValidatingSessionManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* 自定义任务调度器完成
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class SpringSessionValidationScheduler implements SessionValidationScheduler
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(SpringSessionValidationScheduler.class);
|
||||
|
||||
public static final long DEFAULT_SESSION_VALIDATION_INTERVAL = DefaultSessionManager.DEFAULT_SESSION_VALIDATION_INTERVAL;
|
||||
|
||||
/**
|
||||
* 定时器,用于处理超时的挂起请求,也用于连接断开时的重连。
|
||||
*/
|
||||
private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
|
||||
|
||||
private volatile boolean enabled = false;
|
||||
|
||||
/**
|
||||
* The session manager used to validate sessions.
|
||||
*/
|
||||
private ValidatingSessionManager sessionManager;
|
||||
|
||||
/**
|
||||
* The session validation interval in milliseconds.
|
||||
*/
|
||||
private long sessionValidationInterval = DEFAULT_SESSION_VALIDATION_INTERVAL;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public SpringSessionValidationScheduler()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that specifies the session manager that should be used for validating sessions.
|
||||
*
|
||||
* @param sessionManager the <tt>SessionManager</tt> that should be used to validate sessions.
|
||||
*/
|
||||
public SpringSessionValidationScheduler(ValidatingSessionManager sessionManager)
|
||||
{
|
||||
this.sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
public void setSessionManager(ValidatingSessionManager sessionManager)
|
||||
{
|
||||
this.sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled()
|
||||
{
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies how frequently (in milliseconds) this Scheduler will call the
|
||||
* {@link org.apache.shiro.session.mgt.ValidatingSessionManager#validateSessions()
|
||||
* ValidatingSessionManager#validateSessions()} method.
|
||||
*
|
||||
* <p>
|
||||
* Unless this method is called, the default value is {@link #DEFAULT_SESSION_VALIDATION_INTERVAL}.
|
||||
*
|
||||
* @param sessionValidationInterval
|
||||
*/
|
||||
public void setSessionValidationInterval(long sessionValidationInterval)
|
||||
{
|
||||
this.sessionValidationInterval = sessionValidationInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts session validation by creating a spring PeriodicTrigger.
|
||||
*/
|
||||
@Override
|
||||
public void enableSessionValidation()
|
||||
{
|
||||
|
||||
enabled = true;
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Scheduling session validation job using Spring Scheduler with "
|
||||
+ "session validation interval of [" + sessionValidationInterval + "]ms...");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
executorService.scheduleAtFixedRate(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
sessionManager.validateSessions();
|
||||
}
|
||||
}
|
||||
}, 1000, sessionValidationInterval, TimeUnit.MILLISECONDS);
|
||||
|
||||
this.enabled = true;
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Session validation job successfully scheduled with Spring Scheduler.");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (log.isErrorEnabled())
|
||||
{
|
||||
log.error(
|
||||
"Error starting the Spring Scheduler session validation job. Session validation may not occur.",
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableSessionValidation()
|
||||
{
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Stopping Spring Scheduler session validation job...");
|
||||
}
|
||||
|
||||
this.enabled = false;
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
package com.ruoyi.framework.web.controller;
|
||||
|
||||
import java.util.List;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.security.ShiroUtils;
|
||||
import com.ruoyi.framework.web.page.PageDomain;
|
||||
import com.ruoyi.framework.web.page.TableDataInfo;
|
||||
import com.ruoyi.framework.web.page.TableSupport;
|
||||
import com.ruoyi.project.system.user.domain.User;
|
||||
|
||||
/**
|
||||
* web层通用数据处理
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class BaseController
|
||||
{
|
||||
/**
|
||||
* 设置请求分页数据
|
||||
*/
|
||||
protected void startPage()
|
||||
{
|
||||
PageDomain pageDomain = TableSupport.buildPageRequest();
|
||||
Integer pageNum = pageDomain.getPageNum();
|
||||
Integer pageSize = pageDomain.getPageSize();
|
||||
if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize))
|
||||
{
|
||||
String orderBy = pageDomain.getOrderBy();
|
||||
PageHelper.startPage(pageNum, pageSize, orderBy);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 响应请求分页数据
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
protected TableDataInfo getDataTable(List<?> list)
|
||||
{
|
||||
TableDataInfo rspData = new TableDataInfo();
|
||||
rspData.setRows(list);
|
||||
rspData.setTotal(new PageInfo(list).getTotal());
|
||||
return rspData;
|
||||
}
|
||||
|
||||
public User getUser()
|
||||
{
|
||||
return ShiroUtils.getUser();
|
||||
}
|
||||
|
||||
public void setUser(User user)
|
||||
{
|
||||
ShiroUtils.setUser(user);
|
||||
}
|
||||
|
||||
public Long getUserId()
|
||||
{
|
||||
return getUser().getUserId();
|
||||
}
|
||||
|
||||
public String getLoginName()
|
||||
{
|
||||
return getUser().getLoginName();
|
||||
}
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
package com.ruoyi.framework.web.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
|
||||
/**
|
||||
* Entity基类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class BaseEntity implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
/** 搜索值 */
|
||||
private String searchValue;
|
||||
/** 创建者 */
|
||||
private String createBy;
|
||||
/** 创建时间 */
|
||||
private Date createTime;
|
||||
/** 更新者 */
|
||||
private String updateBy;
|
||||
/** 更新时间 */
|
||||
private Date updateTime;
|
||||
/** 备注 */
|
||||
private String remark;
|
||||
|
||||
public String getSearchValue()
|
||||
{
|
||||
return searchValue;
|
||||
}
|
||||
|
||||
public void setSearchValue(String searchValue)
|
||||
{
|
||||
this.searchValue = searchValue;
|
||||
}
|
||||
|
||||
public String getCreateBy()
|
||||
{
|
||||
return createBy;
|
||||
}
|
||||
|
||||
public void setCreateBy(String createBy)
|
||||
{
|
||||
this.createBy = createBy;
|
||||
}
|
||||
|
||||
public String getCreateTimeStr()
|
||||
{
|
||||
return createTime != null ? DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, createTime) : "";
|
||||
}
|
||||
|
||||
public String getCreateDateTimeStr()
|
||||
{
|
||||
return createTime != null ? DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, createTime) : "";
|
||||
}
|
||||
|
||||
public void setCreateTime(Date createTime)
|
||||
{
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public String getUpdateBy()
|
||||
{
|
||||
return updateBy;
|
||||
}
|
||||
|
||||
public void setUpdateBy(String updateBy)
|
||||
{
|
||||
this.updateBy = updateBy;
|
||||
}
|
||||
|
||||
public String getUpdateTimeStr()
|
||||
{
|
||||
return updateTime != null ? DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, updateTime) : "";
|
||||
}
|
||||
|
||||
public String getUpdateDateTimeStr()
|
||||
{
|
||||
return updateTime != null ? DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, updateTime) : "";
|
||||
}
|
||||
|
||||
public void setUpdateTime(Date updateTime)
|
||||
{
|
||||
this.updateTime = updateTime;
|
||||
}
|
||||
|
||||
public String getRemark()
|
||||
{
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark)
|
||||
{
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
package com.ruoyi.framework.web.domain;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* 操作消息提醒
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class Message extends HashMap<String, Object>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 初始化一个新创建的 Message 对象
|
||||
*/
|
||||
public Message()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回错误消息
|
||||
*
|
||||
* @return 错误消息
|
||||
*/
|
||||
public static Message error()
|
||||
{
|
||||
return error(1, "操作失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回错误消息
|
||||
*
|
||||
* @param msg 内容
|
||||
* @return 错误消息
|
||||
*/
|
||||
public static Message error(String msg)
|
||||
{
|
||||
return error(500, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回错误消息
|
||||
*
|
||||
* @param code 错误码
|
||||
* @param msg 内容
|
||||
* @return 错误消息
|
||||
*/
|
||||
public static Message error(int code, String msg)
|
||||
{
|
||||
Message json = new Message();
|
||||
json.put("code", code);
|
||||
json.put("msg", msg);
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回成功消息
|
||||
*
|
||||
* @param msg 内容
|
||||
* @return 成功消息
|
||||
*/
|
||||
public static Message success(String msg)
|
||||
{
|
||||
Message json = new Message();
|
||||
json.put("msg", msg);
|
||||
json.put("code", 0);
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回成功消息
|
||||
*
|
||||
* @return 成功消息
|
||||
*/
|
||||
public static Message success()
|
||||
{
|
||||
return Message.success("操作成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回成功消息
|
||||
*
|
||||
* @param key 键值
|
||||
* @param value 内容
|
||||
* @return 成功消息
|
||||
*/
|
||||
@Override
|
||||
public Message put(String key, Object value)
|
||||
{
|
||||
super.put(key, value);
|
||||
return this;
|
||||
}
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
package com.ruoyi.framework.web.exception;
|
||||
|
||||
import org.apache.shiro.authz.AuthorizationException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
import com.ruoyi.common.exception.DemoModeException;
|
||||
import com.ruoyi.framework.web.domain.Message;
|
||||
|
||||
/**
|
||||
* 自定义异常处理器
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@RestControllerAdvice
|
||||
public class DefaultExceptionHandler
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(DefaultExceptionHandler.class);
|
||||
|
||||
/**
|
||||
* 权限校验失败
|
||||
*/
|
||||
@ExceptionHandler(AuthorizationException.class)
|
||||
public Message handleAuthorizationException(AuthorizationException e)
|
||||
{
|
||||
log.error(e.getMessage(), e);
|
||||
return Message.error("您没有数据的权限,请联系管理员添加");
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求方式不支持
|
||||
*/
|
||||
@ExceptionHandler({ HttpRequestMethodNotSupportedException.class })
|
||||
public Message handleException(HttpRequestMethodNotSupportedException e)
|
||||
{
|
||||
log.error(e.getMessage(), e);
|
||||
return Message.error("不支持' " + e.getMethod() + "'请求");
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截未知的运行时异常
|
||||
*/
|
||||
@ExceptionHandler(RuntimeException.class)
|
||||
public Message notFount(RuntimeException e)
|
||||
{
|
||||
log.error("运行时异常:", e);
|
||||
return Message.error("运行时异常:" + e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统异常
|
||||
*/
|
||||
@ExceptionHandler(Exception.class)
|
||||
public Message handleException(Exception e)
|
||||
{
|
||||
log.error(e.getMessage(), e);
|
||||
return Message.error("服务器错误,请联系管理员");
|
||||
}
|
||||
|
||||
/**
|
||||
* 演示模式异常
|
||||
*/
|
||||
@ExceptionHandler(DemoModeException.class)
|
||||
public Message demoModeException(DemoModeException e)
|
||||
{
|
||||
return Message.error("演示模式,不允许操作");
|
||||
}
|
||||
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
package com.ruoyi.framework.web.page;
|
||||
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 分页数据
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class PageDomain
|
||||
{
|
||||
/** 当前记录起始索引 */
|
||||
private Integer pageNum;
|
||||
/** 每页显示记录数 */
|
||||
private Integer pageSize;
|
||||
/** 排序列 */
|
||||
private String orderByColumn;
|
||||
/** 排序的方向 "desc" 或者 "asc". */
|
||||
private String isAsc;
|
||||
|
||||
public String getOrderBy()
|
||||
{
|
||||
if (StringUtils.isEmpty(orderByColumn))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return orderByColumn + " " + isAsc;
|
||||
}
|
||||
|
||||
public Integer getPageNum()
|
||||
{
|
||||
return pageNum;
|
||||
}
|
||||
|
||||
public void setPageNum(Integer pageNum)
|
||||
{
|
||||
this.pageNum = pageNum;
|
||||
}
|
||||
|
||||
public Integer getPageSize()
|
||||
{
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
public void setPageSize(Integer pageSize)
|
||||
{
|
||||
this.pageSize = pageSize;
|
||||
}
|
||||
|
||||
public String getOrderByColumn()
|
||||
{
|
||||
return orderByColumn;
|
||||
}
|
||||
|
||||
public void setOrderByColumn(String orderByColumn)
|
||||
{
|
||||
this.orderByColumn = orderByColumn;
|
||||
}
|
||||
|
||||
public String getIsAsc()
|
||||
{
|
||||
return isAsc;
|
||||
}
|
||||
|
||||
public void setIsAsc(String isAsc)
|
||||
{
|
||||
this.isAsc = isAsc;
|
||||
}
|
||||
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
package com.ruoyi.framework.web.page;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 表格分页数据对象
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class TableDataInfo implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
/** 总记录数 */
|
||||
private long total;
|
||||
/** 列表数据 */
|
||||
private List<?> rows;
|
||||
|
||||
/**
|
||||
* 表格数据对象
|
||||
*/
|
||||
public TableDataInfo()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*
|
||||
* @param list 列表数据
|
||||
* @param total 总记录数
|
||||
*/
|
||||
public TableDataInfo(List<?> list, int total)
|
||||
{
|
||||
this.rows = list;
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
public long getTotal()
|
||||
{
|
||||
return total;
|
||||
}
|
||||
|
||||
public void setTotal(long total)
|
||||
{
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
public List<?> getRows()
|
||||
{
|
||||
return rows;
|
||||
}
|
||||
|
||||
public void setRows(List<?> rows)
|
||||
{
|
||||
this.rows = rows;
|
||||
}
|
||||
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
package com.ruoyi.framework.web.page;
|
||||
|
||||
import com.ruoyi.common.utils.ServletUtils;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
|
||||
/**
|
||||
* 表格数据处理
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class TableSupport
|
||||
{
|
||||
/**
|
||||
* 封装分页对象
|
||||
*/
|
||||
public static PageDomain getPageDomain()
|
||||
{
|
||||
PageDomain pageDomain = new PageDomain();
|
||||
pageDomain.setPageNum(ServletUtils.getIntParameter(Constants.PAGENUM));
|
||||
pageDomain.setPageSize(ServletUtils.getIntParameter(Constants.PAGESIZE));
|
||||
pageDomain.setOrderByColumn(ServletUtils.getStrParameter(Constants.ORDERBYCOLUMN));
|
||||
pageDomain.setIsAsc(ServletUtils.getStrParameter(Constants.ISASC));
|
||||
return pageDomain;
|
||||
}
|
||||
|
||||
public static PageDomain buildPageRequest()
|
||||
{
|
||||
return getPageDomain();
|
||||
}
|
||||
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package com.ruoyi.framework.web.service;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.ruoyi.project.system.config.service.IConfigService;
|
||||
|
||||
/**
|
||||
* RuoYi首创 html调用 thymeleaf 实现参数管理
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class ConfigService
|
||||
{
|
||||
@Autowired
|
||||
private IConfigService configService;
|
||||
|
||||
/**
|
||||
* 根据键名查询参数配置信息
|
||||
*
|
||||
* @param configName 参数名称
|
||||
* @return 参数键值
|
||||
*/
|
||||
public String selectConfigByKey(String configKey)
|
||||
{
|
||||
return configService.selectConfigByKey(configKey);
|
||||
}
|
||||
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
package com.ruoyi.framework.web.service;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.ruoyi.project.system.dict.domain.DictData;
|
||||
import com.ruoyi.project.system.dict.service.IDictDataService;
|
||||
|
||||
/**
|
||||
* RuoYi首创 html调用 thymeleaf 实现字典读取
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class DictService
|
||||
{
|
||||
@Autowired
|
||||
private IDictDataService dictDataService;
|
||||
|
||||
/**
|
||||
* 根据字典类型查询字典数据信息
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @return 参数键值
|
||||
*/
|
||||
public List<DictData> selectDictData(String dictType)
|
||||
{
|
||||
return dictDataService.selectDictDataByType(dictType);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user