mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-09-20 02:29:27 +08:00
!100 Jboot,jFinal插件更新,优化解决缓存序列化出现乱码的问题
Merge pull request !100 from nextStar/dev
This commit is contained in:
@@ -21,6 +21,8 @@
|
|||||||
<module>sa-token-spring-boot-starter</module>
|
<module>sa-token-spring-boot-starter</module>
|
||||||
<module>sa-token-reactor-spring-boot-starter</module>
|
<module>sa-token-reactor-spring-boot-starter</module>
|
||||||
<module>sa-token-solon-plugin</module>
|
<module>sa-token-solon-plugin</module>
|
||||||
|
<module>sa-token-jboot-plugin</module>
|
||||||
|
<module>sa-token-jfinal-plugin</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
</project>
|
</project>
|
55
sa-token-starter/sa-token-jboot-plugin/pom.xml
Normal file
55
sa-token-starter/sa-token-jboot-plugin/pom.xml
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>sa-token-starter</artifactId>
|
||||||
|
<groupId>cn.dev33</groupId>
|
||||||
|
<version>1.29.0</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<artifactId>sa-token-jboot-plugin</artifactId>
|
||||||
|
<description>jboot integrate sa-token</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jboot</groupId>
|
||||||
|
<artifactId>jboot</artifactId>
|
||||||
|
<version>3.11.4</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.dev33</groupId>
|
||||||
|
<artifactId>sa-token-core</artifactId>
|
||||||
|
<version>${sa-token-version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.dev33</groupId>
|
||||||
|
<artifactId>sa-token-servlet</artifactId>
|
||||||
|
<version>${sa-token-version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.6.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
<compilerArgument>-parameters</compilerArgument>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
@@ -0,0 +1,60 @@
|
|||||||
|
package cn.dev33.satoken.jboot;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class PathAnalyzer {
|
||||||
|
|
||||||
|
private static Map<String, PathAnalyzer> cached = new LinkedHashMap();
|
||||||
|
private Pattern pattern;
|
||||||
|
|
||||||
|
public static PathAnalyzer get(String expr) {
|
||||||
|
PathAnalyzer pa = (PathAnalyzer)cached.get(expr);
|
||||||
|
if (pa == null) {
|
||||||
|
synchronized(expr.intern()) {
|
||||||
|
pa = (PathAnalyzer)cached.get(expr);
|
||||||
|
if (pa == null) {
|
||||||
|
pa = new PathAnalyzer(expr);
|
||||||
|
cached.put(expr, pa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pa;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PathAnalyzer(String expr) {
|
||||||
|
this.pattern = Pattern.compile(exprCompile(expr), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Matcher matcher(String uri) {
|
||||||
|
return this.pattern.matcher(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matches(String uri) {
|
||||||
|
return this.pattern.matcher(uri).find();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String exprCompile(String expr) {
|
||||||
|
String p = expr.replace(".", "\\.");
|
||||||
|
p = p.replace("$", "\\$");
|
||||||
|
p = p.replace("**", ".[]");
|
||||||
|
p = p.replace("*", "[^/]*");
|
||||||
|
if (p.indexOf("{") >= 0) {
|
||||||
|
if (p.indexOf("_}") > 0) {
|
||||||
|
p = p.replaceAll("\\{[^\\}]+?\\_\\}", "(.+?)");
|
||||||
|
}
|
||||||
|
|
||||||
|
p = p.replaceAll("\\{[^\\}]+?\\}", "([^/]+?)");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!p.startsWith("/")) {
|
||||||
|
p = "/" + p;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = p.replace(".[]", ".*");
|
||||||
|
return "^" + p + "$";
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,16 @@
|
|||||||
|
package cn.dev33.satoken.jboot;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.strategy.SaStrategy;
|
||||||
|
import com.jfinal.aop.Interceptor;
|
||||||
|
import com.jfinal.aop.Invocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注解式鉴权 - 拦截器
|
||||||
|
*/
|
||||||
|
public class SaAnnotationInterceptor implements Interceptor {
|
||||||
|
@Override
|
||||||
|
public void intercept(Invocation invocation) {
|
||||||
|
SaStrategy.me.checkMethodAnnotation.accept((invocation.getMethod()));
|
||||||
|
invocation.invoke();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,57 @@
|
|||||||
|
package cn.dev33.satoken.jboot;
|
||||||
|
|
||||||
|
import com.jfinal.log.Log;
|
||||||
|
import io.jboot.components.serializer.JbootSerializer;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.ObjectInputStream;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
|
||||||
|
public class SaJdkSerializer implements JbootSerializer {
|
||||||
|
|
||||||
|
private static final Log LOG = Log.getLog(SaJdkSerializer.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] serialize(Object value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ObjectOutputStream objectOut = null;
|
||||||
|
try {
|
||||||
|
ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(1024);
|
||||||
|
objectOut = new ObjectOutputStream(bytesOut);
|
||||||
|
objectOut.writeObject(value);
|
||||||
|
objectOut.flush();
|
||||||
|
return bytesOut.toByteArray();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if(objectOut != null)
|
||||||
|
try {objectOut.close();} catch (Exception e) {
|
||||||
|
LOG.error(e.getMessage(), e);}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object deserialize(byte[] bytes) {
|
||||||
|
if (bytes == null || bytes.length == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ObjectInputStream objectInput = null;
|
||||||
|
try {
|
||||||
|
ByteArrayInputStream bytesInput = new ByteArrayInputStream(bytes);
|
||||||
|
objectInput = new ObjectInputStream(bytesInput);
|
||||||
|
return objectInput.readObject();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if (objectInput != null)
|
||||||
|
try {objectInput.close();} catch (Exception e) {LOG.error(e.getMessage(), e);}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,459 @@
|
|||||||
|
package cn.dev33.satoken.jboot;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
|
import com.jfinal.log.Log;
|
||||||
|
import io.jboot.Jboot;
|
||||||
|
import io.jboot.components.serializer.JbootSerializer;
|
||||||
|
import io.jboot.components.serializer.JbootSerializerManager;
|
||||||
|
import io.jboot.exception.JbootIllegalConfigException;
|
||||||
|
import io.jboot.utils.StrUtil;
|
||||||
|
import redis.clients.jedis.Jedis;
|
||||||
|
import redis.clients.jedis.JedisPool;
|
||||||
|
import redis.clients.jedis.JedisPoolConfig;
|
||||||
|
import redis.clients.jedis.exceptions.JedisConnectionException;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class SaJedisImpl {
|
||||||
|
|
||||||
|
private final JbootSerializer serializer;
|
||||||
|
|
||||||
|
protected JedisPool jedisPool;
|
||||||
|
private static final Log LOG = Log.getLog(SaJedisImpl.class);
|
||||||
|
private final SaRedisConfig config;
|
||||||
|
public SaJedisImpl(SaRedisConfig config) {
|
||||||
|
if (config == null || StrUtil.isBlank(config.getSerializer())) {
|
||||||
|
serializer = Jboot.getSerializer();
|
||||||
|
} else {
|
||||||
|
serializer = JbootSerializerManager.me().getSerializer(config.getSerializer());
|
||||||
|
}
|
||||||
|
this.config = config;
|
||||||
|
assert this.config != null;
|
||||||
|
String host = this.config.getHost();
|
||||||
|
Integer port = this.config.getPort();
|
||||||
|
Integer timeout = this.config.getTimeout();
|
||||||
|
String password = this.config.getPassword();
|
||||||
|
Integer database = this.config.getSaDb()==null?this.config.getDatabase():this.config.getSaDb();
|
||||||
|
String clientName = this.config.getClientName();
|
||||||
|
|
||||||
|
if (host.contains(":")) {
|
||||||
|
port = Integer.valueOf(host.split(":")[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
JedisPoolConfig poolConfig = new JedisPoolConfig();
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(config.getTestWhileIdle())) {
|
||||||
|
poolConfig.setTestWhileIdle(config.getTestWhileIdle());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(config.getTestOnBorrow())) {
|
||||||
|
poolConfig.setTestOnBorrow(config.getTestOnBorrow());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(config.getTestOnCreate())) {
|
||||||
|
poolConfig.setTestOnCreate(config.getTestOnCreate());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(config.getTestOnReturn())) {
|
||||||
|
poolConfig.setTestOnReturn(config.getTestOnReturn());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(config.getMinEvictableIdleTimeMillis())) {
|
||||||
|
poolConfig.setMinEvictableIdleTime(Duration.ofMillis(config.getMinEvictableIdleTimeMillis()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(config.getTimeBetweenEvictionRunsMillis())) {
|
||||||
|
poolConfig.setSoftMinEvictableIdleTime(Duration.ofMillis(config.getTimeBetweenEvictionRunsMillis()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(config.getNumTestsPerEvictionRun())) {
|
||||||
|
poolConfig.setNumTestsPerEvictionRun(config.getNumTestsPerEvictionRun());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(config.getMaxTotal())) {
|
||||||
|
poolConfig.setMaxTotal(config.getMaxTotal());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(config.getMaxIdle())) {
|
||||||
|
poolConfig.setMaxIdle(config.getMaxIdle());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(config.getMinIdle())) {
|
||||||
|
poolConfig.setMinIdle(config.getMinIdle());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(config.getMaxWaitMillis())) {
|
||||||
|
poolConfig.setMaxWaitMillis(config.getMaxWaitMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.jedisPool = new JedisPool(poolConfig, host, port, timeout, timeout, password, database, clientName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Value,如无返空
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String get(String key){
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try{
|
||||||
|
return jedis.get(key);
|
||||||
|
}finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 写入Value
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
public void set(String key, String value) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try{
|
||||||
|
jedis.set(key, value);
|
||||||
|
}finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入Value,并设定存活时间 (单位: 秒)
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
* @param timeout
|
||||||
|
*/
|
||||||
|
public void setex(String key, String value, long timeout){
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try{
|
||||||
|
jedis.setex(key,timeout,value);
|
||||||
|
}finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除Value
|
||||||
|
* @param key
|
||||||
|
*/
|
||||||
|
public void del(String key) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try{
|
||||||
|
jedis.del(key);
|
||||||
|
}finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Value的剩余存活时间 (单位: 秒)
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public long ttl(String key) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try{
|
||||||
|
return jedis.ttl(key);
|
||||||
|
}finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void expire(String key,long timeout){
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
jedis.expire(key,timeout);
|
||||||
|
} finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Object,如无返空
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Object getObject(String key) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
return valueFromBytes(jedis.get(keyToBytes(key)));
|
||||||
|
} finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入Object
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
public void setObject(Object key, Object value) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
jedis.set(keyToBytes(key), valueToBytes(value));
|
||||||
|
} finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入Object,并设定存活时间 (单位: 秒)
|
||||||
|
* @param key
|
||||||
|
* @param object
|
||||||
|
* @param timeout
|
||||||
|
*/
|
||||||
|
public void setexObject(String key, Object object,long timeout) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
jedis.setex(keyToBytes(key),timeout, valueToBytes(object));
|
||||||
|
} finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除Object
|
||||||
|
* @param key
|
||||||
|
*/
|
||||||
|
public void deleteObject(String key) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
jedis.del(keyToBytes(key));
|
||||||
|
} finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getObjectTimeout(String key) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
return getJedis().ttl(keyToBytes(key));
|
||||||
|
} finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改Object的剩余存活时间 (单位: 秒)
|
||||||
|
* @param key
|
||||||
|
* @param timeout
|
||||||
|
*/
|
||||||
|
public void expireObject(String key, long timeout) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
jedis.expire(keyToBytes(key), timeout);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找所有符合给定模式 pattern 的 key 。
|
||||||
|
* KEYS * 匹配数据库中所有 key 。
|
||||||
|
* KEYS h?llo 匹配 hello , hallo 和 hxllo 等。
|
||||||
|
* KEYS h*llo 匹配 hllo 和 heeeeello 等。
|
||||||
|
* KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo 。
|
||||||
|
* 特殊符号用 \ 隔开
|
||||||
|
*/
|
||||||
|
public Set<String> keys(String pattern) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
return jedis.keys(pattern);
|
||||||
|
} finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将哈希表 key 中的域 field 的值设为 value 。
|
||||||
|
* 如果 key 不存在,一个新的哈希表被创建并进行 HSET 操作。
|
||||||
|
* 如果域 field 已经存在于哈希表中,旧值将被覆盖。
|
||||||
|
*/
|
||||||
|
public Long hset(String key, String field, String value) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
return jedis.hset(key, field, value);
|
||||||
|
} finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同时将多个 field-value (域-值)对设置到哈希表 key 中。
|
||||||
|
* 此命令会覆盖哈希表中已存在的域。
|
||||||
|
* 如果 key 不存在,一个空哈希表被创建并执行 HMSET 操作。
|
||||||
|
*/
|
||||||
|
public String hmset(String key, Map<String, String> hash) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
return jedis.hmset(key,hash);
|
||||||
|
} finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 返回哈希表 key 中给定域 field 的值。
|
||||||
|
* @param key
|
||||||
|
* @param field
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String hget(String key,String field){
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
return jedis.hget(key,field);
|
||||||
|
} finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回哈希表 key 中,一个或多个给定域的值。
|
||||||
|
* 如果给定的域不存在于哈希表,那么返回一个 nil 值。
|
||||||
|
* 因为不存在的 key 被当作一个空哈希表来处理,所以对一个不存在的 key 进行 HMGET 操作将返回一个只带有 nil 值的表。
|
||||||
|
*/
|
||||||
|
public List<String> hmget(String key, String... fields) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
return jedis.hmget(key,fields);
|
||||||
|
} finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略。
|
||||||
|
* @param key
|
||||||
|
* @param fields
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Long hdel(String key, String... fields) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
return jedis.hdel(key,fields);
|
||||||
|
} finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 查看哈希表 key 中,给定域 field 是否存在。
|
||||||
|
* @param key
|
||||||
|
* @param field
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean hexists(String key, String field){
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
return jedis.hexists(key,field);
|
||||||
|
} finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 返回哈希表 key 中,所有的域和值。
|
||||||
|
* 在返回值里,紧跟每个域名(field name)之后是域的值(value),所以返回值的长度是哈希表大小的两倍。
|
||||||
|
*/
|
||||||
|
public Map<String, String> hgetAll(String key) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
return jedis.hgetAll(key);
|
||||||
|
} finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回哈希表 key 中所有域的值。
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<String> hvals(String key) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
return jedis.hvals(key);
|
||||||
|
} finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回哈希表 key 中的所有域。
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Set<String> hkeys(String key){
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
return jedis.hkeys(key);
|
||||||
|
} finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回哈希表 key 中域的数量。
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Long hlen(String key){
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
return jedis.hlen(key);
|
||||||
|
} finally {
|
||||||
|
returnResource(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Jedis getJedis() {
|
||||||
|
try {
|
||||||
|
return jedisPool.getResource();
|
||||||
|
} catch (JedisConnectionException e) {
|
||||||
|
throw new JbootIllegalConfigException("can not connect to redis host " + config.getHost() + ":" + config.getPort() + " ," +
|
||||||
|
" cause : " + e.toString(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void returnResource(Jedis jedis) {
|
||||||
|
if (jedis != null) {
|
||||||
|
jedis.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] keyToBytes(Object key) {
|
||||||
|
return key.toString().getBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String bytesToKey(byte[] bytes) {
|
||||||
|
return new String(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] valueToBytes(Object value) {
|
||||||
|
return serializer.serialize(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object valueFromBytes(byte[] bytes) {
|
||||||
|
if (bytes == null || bytes.length == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return serializer.deserialize(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索数据
|
||||||
|
* @param prefix
|
||||||
|
* @param keyword
|
||||||
|
* @param start
|
||||||
|
* @param size
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<String> searchData(String prefix, String keyword, int start, int size) {
|
||||||
|
Set<String> keys = getJedis().keys(prefix + "*" + keyword + "*");
|
||||||
|
List<String> list = new ArrayList<String>(keys);
|
||||||
|
return SaFoxUtil.searchList(list, start, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,27 @@
|
|||||||
|
package cn.dev33.satoken.jboot;
|
||||||
|
|
||||||
|
import io.jboot.app.config.annotation.ConfigModel;
|
||||||
|
import io.jboot.support.redis.JbootRedisConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SA-Token redis缓存配置,获取database
|
||||||
|
*/
|
||||||
|
@ConfigModel(
|
||||||
|
prefix = "jboot.redis"
|
||||||
|
)
|
||||||
|
public class SaRedisConfig extends JbootRedisConfig{
|
||||||
|
|
||||||
|
private Integer saDb;
|
||||||
|
|
||||||
|
public SaRedisConfig(){
|
||||||
|
|
||||||
|
}
|
||||||
|
public Integer getSaDb() {
|
||||||
|
return this.saDb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSaDb(Integer saDb) {
|
||||||
|
this.saDb = saDb;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,38 @@
|
|||||||
|
package cn.dev33.satoken.jboot;
|
||||||
|
|
||||||
|
import io.jboot.Jboot;
|
||||||
|
|
||||||
|
public class SaRedisManager {
|
||||||
|
|
||||||
|
private static SaRedisManager manager = new SaRedisManager();
|
||||||
|
|
||||||
|
private SaRedisManager() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SaRedisManager me() {
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SaJedisImpl redis;
|
||||||
|
|
||||||
|
public SaJedisImpl getRedis() {
|
||||||
|
if (redis == null) {
|
||||||
|
SaRedisConfig config = Jboot.config(SaRedisConfig.class);
|
||||||
|
redis = getRedis(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
return redis;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SaJedisImpl getRedis(SaRedisConfig config) {
|
||||||
|
if (config == null || !config.isConfigOk()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return getJedisClient(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private SaJedisImpl getJedisClient(SaRedisConfig config) {
|
||||||
|
return new SaJedisImpl(config);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,52 @@
|
|||||||
|
package cn.dev33.satoken.jboot;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.context.SaTokenContext;
|
||||||
|
import cn.dev33.satoken.context.model.SaRequest;
|
||||||
|
import cn.dev33.satoken.context.model.SaResponse;
|
||||||
|
import cn.dev33.satoken.context.model.SaStorage;
|
||||||
|
import cn.dev33.satoken.servlet.model.SaRequestForServlet;
|
||||||
|
import cn.dev33.satoken.servlet.model.SaResponseForServlet;
|
||||||
|
import cn.dev33.satoken.servlet.model.SaStorageForServlet;
|
||||||
|
import io.jboot.web.controller.JbootControllerContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sa-Token 上线文处理器 [Jboot 版本实现]
|
||||||
|
*/
|
||||||
|
public class SaTokenContextForJboot implements SaTokenContext {
|
||||||
|
/**
|
||||||
|
* 获取当前请求的Request对象
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public SaRequest getRequest() {
|
||||||
|
return new SaRequestForServlet(JbootControllerContext.get().getRequest());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前请求的Response对象
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public SaResponse getResponse() {
|
||||||
|
return new SaResponseForServlet(JbootControllerContext.get().getResponse());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前请求的 [存储器] 对象
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public SaStorage getStorage() {
|
||||||
|
return new SaStorageForServlet(JbootControllerContext.get().getRequest());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验指定路由匹配符是否可以匹配成功指定路径
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean matchPath(String pattern, String path) {
|
||||||
|
return PathAnalyzer.get(pattern).matches(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid() {
|
||||||
|
return SaTokenContext.super.isValid();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,211 @@
|
|||||||
|
package cn.dev33.satoken.jboot;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.dao.SaTokenDao;
|
||||||
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
|
import io.jboot.Jboot;
|
||||||
|
import io.jboot.exception.JbootIllegalConfigException;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class SaTokenDaoRedis implements SaTokenDao {
|
||||||
|
|
||||||
|
private SaJedisImpl redis;
|
||||||
|
/**
|
||||||
|
* 标记:是否已初始化成功
|
||||||
|
*/
|
||||||
|
public boolean isInit;
|
||||||
|
|
||||||
|
public SaTokenDaoRedis(){
|
||||||
|
SaRedisConfig redisConfig = Jboot.config(SaRedisConfig.class);
|
||||||
|
redisConfig.setSerializer("cn.dev33.satoken.jboot.SaJdkSerializer");
|
||||||
|
//优先使用 jboot.cache.redis 的配置
|
||||||
|
if (redisConfig.isConfigOk()) {
|
||||||
|
redis = SaRedisManager.me().getRedis(redisConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (redis == null) {
|
||||||
|
this.isInit = false;
|
||||||
|
throw new JbootIllegalConfigException("can not get redis, please check your jboot.properties , please correct config jboot.cache.redis.host or jboot.redis.host ");
|
||||||
|
}else{
|
||||||
|
this.isInit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Value,如无返空
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String get(String key) {
|
||||||
|
return redis.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入Value,并设定存活时间 (单位: 秒)
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
* @param timeout
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void set(String key, String value, long timeout) {
|
||||||
|
if(timeout == 0 || timeout <= SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(timeout == SaTokenDao.NEVER_EXPIRE) {
|
||||||
|
redis.set(key, value);
|
||||||
|
}else{
|
||||||
|
redis.setex(key,value,timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改指定key-value键值对 (过期时间不变)
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void update(String key, String value) {
|
||||||
|
long expire = getTimeout(key);
|
||||||
|
// -2 = 无此键
|
||||||
|
if(expire == SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.set(key,value,expire);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除Value
|
||||||
|
* @param key
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void delete(String key) {
|
||||||
|
redis.del(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Value的剩余存活时间 (单位: 秒)
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long getTimeout(String key) {
|
||||||
|
return redis.ttl(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改Value的剩余存活时间 (单位: 秒)
|
||||||
|
* @param key
|
||||||
|
* @param timeout
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void updateTimeout(String key, long timeout) {
|
||||||
|
//判断是否想要设置为永久
|
||||||
|
if(timeout == SaTokenDao.NEVER_EXPIRE) {
|
||||||
|
long expire = getTimeout(key);
|
||||||
|
if(expire == SaTokenDao.NEVER_EXPIRE) {
|
||||||
|
// 如果其已经被设置为永久,则不作任何处理
|
||||||
|
} else {
|
||||||
|
// 如果尚未被设置为永久,那么再次set一次
|
||||||
|
this.set(key, this.get(key), timeout);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
redis.expire(key,timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Object,如无返空
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Object getObject(String key) {
|
||||||
|
return redis.getObject(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入Object,并设定存活时间 (单位: 秒)
|
||||||
|
* @param key
|
||||||
|
* @param object
|
||||||
|
* @param timeout
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setObject(String key, Object object, long timeout) {
|
||||||
|
if(timeout == 0 || timeout <= SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(timeout == SaTokenDao.NEVER_EXPIRE) {
|
||||||
|
redis.setObject(key, object);
|
||||||
|
}else{
|
||||||
|
redis.setexObject(key,object,timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新Object (过期时间不变)
|
||||||
|
* @param key
|
||||||
|
* @param object
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void updateObject(String key, Object object) {
|
||||||
|
long expire = getObjectTimeout(key);
|
||||||
|
// -2 = 无此键
|
||||||
|
if(expire == SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.setObject(key, object, expire);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除Object
|
||||||
|
* @param key
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void deleteObject(String key) {
|
||||||
|
redis.deleteObject(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getObjectTimeout(String key) {
|
||||||
|
return redis.getObjectTimeout(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改Object的剩余存活时间 (单位: 秒)
|
||||||
|
* @param key
|
||||||
|
* @param timeout
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void updateObjectTimeout(String key, long timeout) {
|
||||||
|
//判断是否想要设置为永久
|
||||||
|
if(timeout == SaTokenDao.NEVER_EXPIRE) {
|
||||||
|
long expire = getTimeout(key);
|
||||||
|
if(expire == SaTokenDao.NEVER_EXPIRE) {
|
||||||
|
// 如果其已经被设置为永久,则不作任何处理
|
||||||
|
} else {
|
||||||
|
// 如果尚未被设置为永久,那么再次set一次
|
||||||
|
this.setObject(key, this.get(key), timeout);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
redis.expireObject(key,timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索数据
|
||||||
|
* @param prefix
|
||||||
|
* @param keyword
|
||||||
|
* @param start
|
||||||
|
* @param size
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<String> searchData(String prefix, String keyword, int start, int size) {
|
||||||
|
Set<String> keys = redis.keys(prefix + "*" + keyword + "*");
|
||||||
|
List<String> list = new ArrayList<String>(keys);
|
||||||
|
return SaFoxUtil.searchList(list, start, size);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,154 @@
|
|||||||
|
package cn.dev33.satoken.jboot;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.exception.SaTokenException;
|
||||||
|
import cn.dev33.satoken.filter.SaFilterAuthStrategy;
|
||||||
|
import cn.dev33.satoken.filter.SaFilterErrorStrategy;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SaTokenPathFilter {
|
||||||
|
|
||||||
|
// ------------------------ 设置此过滤器 拦截 & 放行 的路由
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拦截路由
|
||||||
|
*/
|
||||||
|
private List<String> includeList = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 放行路由
|
||||||
|
*/
|
||||||
|
private List<String> excludeList = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加 [拦截路由]
|
||||||
|
* @param paths 路由
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaTokenPathFilter addInclude(String... paths) {
|
||||||
|
includeList.addAll(Arrays.asList(paths));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加 [放行路由]
|
||||||
|
* @param paths 路由
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaTokenPathFilter addExclude(String... paths) {
|
||||||
|
excludeList.addAll(Arrays.asList(paths));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入 [拦截路由] 集合
|
||||||
|
* @param pathList 路由集合
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaTokenPathFilter setIncludeList(List<String> pathList) {
|
||||||
|
includeList = pathList;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入 [放行路由] 集合
|
||||||
|
* @param pathList 路由集合
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaTokenPathFilter setExcludeList(List<String> pathList) {
|
||||||
|
excludeList = pathList;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [拦截路由] 集合
|
||||||
|
* @return see note
|
||||||
|
*/
|
||||||
|
public List<String> getIncludeList() {
|
||||||
|
return includeList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [放行路由] 集合
|
||||||
|
* @return see note
|
||||||
|
*/
|
||||||
|
public List<String> getExcludeList() {
|
||||||
|
return excludeList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------ 钩子函数
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 认证函数:每次请求执行
|
||||||
|
*/
|
||||||
|
public SaFilterAuthStrategy auth = r -> {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常处理函数:每次[认证函数]发生异常时执行此函数
|
||||||
|
*/
|
||||||
|
public SaFilterErrorStrategy error = e -> {
|
||||||
|
throw new SaTokenException(e);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前置函数:在每次[认证函数]之前执行
|
||||||
|
*/
|
||||||
|
public SaFilterAuthStrategy beforeAuth = r -> {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入[认证函数]: 每次请求执行
|
||||||
|
* @param auth see note
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaTokenPathFilter setAuth(SaFilterAuthStrategy auth) {
|
||||||
|
this.auth = auth;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入[异常处理函数]:每次[认证函数]发生异常时执行此函数
|
||||||
|
* @param error see note
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaTokenPathFilter setError(SaFilterErrorStrategy error) {
|
||||||
|
this.error = error;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入[前置函数]:在每次[认证函数]之前执行
|
||||||
|
* @param beforeAuth see note
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaTokenPathFilter setBeforeAuth(SaFilterAuthStrategy beforeAuth) {
|
||||||
|
this.beforeAuth = beforeAuth;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*@Override
|
||||||
|
public void doFilter(Controller ctx, FilterChain chain) throws Throwable {
|
||||||
|
try {
|
||||||
|
// 执行全局过滤器
|
||||||
|
SaRouter.match(includeList).notMatch(excludeList).check(r -> {
|
||||||
|
beforeAuth.run(null);
|
||||||
|
auth.run(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (StopMatchException e) {
|
||||||
|
|
||||||
|
} catch (Throwable e) {
|
||||||
|
// 1. 获取异常处理策略结果
|
||||||
|
String result = (e instanceof BackResultException) ? e.getMessage() : String.valueOf(error.run(e));
|
||||||
|
// 2. 写入输出流
|
||||||
|
ctx.renderText(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行
|
||||||
|
chain.doFilter(ctx);
|
||||||
|
}*/
|
||||||
|
}
|
@@ -0,0 +1,35 @@
|
|||||||
|
package cn.dev33.satoken.jboot.test;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import io.jboot.app.JbootApplication;
|
||||||
|
import io.jboot.web.controller.JbootController;
|
||||||
|
import io.jboot.web.controller.annotation.RequestMapping;
|
||||||
|
|
||||||
|
@RequestMapping("/")
|
||||||
|
public class AppRun extends JbootController {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
JbootApplication.run(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void index(){
|
||||||
|
renderText("index");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doLogin(){
|
||||||
|
StpUtil.login(10001);
|
||||||
|
//赋值角色
|
||||||
|
renderText("登录成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getLoginInfo(){
|
||||||
|
System.out.println("是否登录:"+StpUtil.isLogin());
|
||||||
|
System.out.println("登录信息"+StpUtil.getTokenInfo());
|
||||||
|
renderJson(StpUtil.getTokenInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SaCheckRole("super-admin")
|
||||||
|
public void add(){
|
||||||
|
renderText("超级管理员方法!");
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,85 @@
|
|||||||
|
package cn.dev33.satoken.jboot.test;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.SaManager;
|
||||||
|
import cn.dev33.satoken.config.SaCookieConfig;
|
||||||
|
import cn.dev33.satoken.config.SaTokenConfig;
|
||||||
|
import cn.dev33.satoken.context.SaTokenContext;
|
||||||
|
import cn.dev33.satoken.jboot.SaAnnotationInterceptor;
|
||||||
|
import cn.dev33.satoken.jboot.SaTokenContextForJboot;
|
||||||
|
import cn.dev33.satoken.jboot.SaTokenDaoRedis;
|
||||||
|
import cn.dev33.satoken.util.SaTokenConsts;
|
||||||
|
import com.jfinal.config.Constants;
|
||||||
|
import com.jfinal.config.Interceptors;
|
||||||
|
import com.jfinal.config.Routes;
|
||||||
|
import com.jfinal.template.Engine;
|
||||||
|
import io.jboot.aop.jfinal.JfinalHandlers;
|
||||||
|
import io.jboot.aop.jfinal.JfinalPlugins;
|
||||||
|
import io.jboot.core.listener.JbootAppListener;
|
||||||
|
|
||||||
|
public class AtteStartListener implements JbootAppListener {
|
||||||
|
public void onInit() {
|
||||||
|
SaTokenContext saTokenContext = new SaTokenContextForJboot();
|
||||||
|
SaManager.setSaTokenContext(saTokenContext);
|
||||||
|
SaManager.setStpInterface(new StpInterfaceImpl());
|
||||||
|
SaTokenConfig saTokenConfig = new SaTokenConfig();
|
||||||
|
saTokenConfig.setTokenStyle(SaTokenConsts.TOKEN_STYLE_SIMPLE_UUID);
|
||||||
|
saTokenConfig.setTimeout(60*60*4); //登录有效时间4小时
|
||||||
|
saTokenConfig.setActivityTimeout(30*60); //半小时无操作过期处理
|
||||||
|
saTokenConfig.setIsShare(false);
|
||||||
|
saTokenConfig.setTokenName("token"); //更换satoken的名称
|
||||||
|
saTokenConfig.setCookie(new SaCookieConfig().setHttpOnly(true)); //开启cookies的httponly属性
|
||||||
|
SaManager.setConfig(saTokenConfig);
|
||||||
|
SaManager.setSaTokenDao(new SaTokenDaoRedis());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConstantConfig(Constants constants) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRouteConfig(Routes routes) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEngineConfig(Engine engine) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPluginConfig(JfinalPlugins plugins) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInterceptorConfig(Interceptors interceptors) {
|
||||||
|
//开启注解方式权限验证
|
||||||
|
interceptors.add(new SaAnnotationInterceptor());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHandlerConfig(JfinalHandlers handlers) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStartBefore() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStartFinish() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStop() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,23 @@
|
|||||||
|
package cn.dev33.satoken.jboot.test;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.StpInterface;
|
||||||
|
import io.jboot.aop.annotation.Bean;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public class StpInterfaceImpl implements StpInterface {
|
||||||
|
@Override
|
||||||
|
public List<String> getPermissionList(Object o, String s) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getRoleList(Object o, String s) {
|
||||||
|
List<String> list = new ArrayList<String>();
|
||||||
|
list.add("admin");
|
||||||
|
list.add("super-admin");
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
87
sa-token-starter/sa-token-jfinal-plugin/pom.xml
Normal file
87
sa-token-starter/sa-token-jfinal-plugin/pom.xml
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>sa-token-starter</artifactId>
|
||||||
|
<groupId>cn.dev33</groupId>
|
||||||
|
<version>1.28.0</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<artifactId>sa-token-jfinal-plugin</artifactId>
|
||||||
|
<description>jfinal integrate sa-token</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<version>1.7.24</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.jfinal</groupId>
|
||||||
|
<artifactId>jfinal-undertow</artifactId>
|
||||||
|
<version>2.8</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.jfinal</groupId>
|
||||||
|
<artifactId>jfinal</artifactId>
|
||||||
|
<version>4.9.17</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.dev33</groupId>
|
||||||
|
<artifactId>sa-token-core</artifactId>
|
||||||
|
<version>${sa-token-version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.dev33</groupId>
|
||||||
|
<artifactId>sa-token-servlet</artifactId>
|
||||||
|
<version>${sa-token-version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-pool2</artifactId>
|
||||||
|
<version>2.11.1</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>redis.clients</groupId>
|
||||||
|
<artifactId>jedis</artifactId>
|
||||||
|
<version>3.7.0</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.ruedigermoeller</groupId>
|
||||||
|
<artifactId>fst</artifactId>
|
||||||
|
<version>2.29</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.6.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
<compilerArgument>-parameters</compilerArgument>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
@@ -0,0 +1,60 @@
|
|||||||
|
package cn.dev33.satoken.jfinal;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class PathAnalyzer {
|
||||||
|
|
||||||
|
private static Map<String, PathAnalyzer> cached = new LinkedHashMap();
|
||||||
|
private Pattern pattern;
|
||||||
|
|
||||||
|
public static PathAnalyzer get(String expr) {
|
||||||
|
PathAnalyzer pa = (PathAnalyzer)cached.get(expr);
|
||||||
|
if (pa == null) {
|
||||||
|
synchronized(expr.intern()) {
|
||||||
|
pa = (PathAnalyzer)cached.get(expr);
|
||||||
|
if (pa == null) {
|
||||||
|
pa = new PathAnalyzer(expr);
|
||||||
|
cached.put(expr, pa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pa;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PathAnalyzer(String expr) {
|
||||||
|
this.pattern = Pattern.compile(exprCompile(expr), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Matcher matcher(String uri) {
|
||||||
|
return this.pattern.matcher(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matches(String uri) {
|
||||||
|
return this.pattern.matcher(uri).find();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String exprCompile(String expr) {
|
||||||
|
String p = expr.replace(".", "\\.");
|
||||||
|
p = p.replace("$", "\\$");
|
||||||
|
p = p.replace("**", ".[]");
|
||||||
|
p = p.replace("*", "[^/]*");
|
||||||
|
if (p.contains("{")) {
|
||||||
|
if (p.indexOf("_}") > 0) {
|
||||||
|
p = p.replaceAll("\\{[^\\}]+?\\_\\}", "(.+?)");
|
||||||
|
}
|
||||||
|
|
||||||
|
p = p.replaceAll("\\{[^\\}]+?\\}", "([^/]+?)");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!p.startsWith("/")) {
|
||||||
|
p = "/" + p;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = p.replace(".[]", ".*");
|
||||||
|
return "^" + p + "$";
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,16 @@
|
|||||||
|
package cn.dev33.satoken.jfinal;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.strategy.SaStrategy;
|
||||||
|
import com.jfinal.aop.Interceptor;
|
||||||
|
import com.jfinal.aop.Invocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注解式鉴权 - 拦截器
|
||||||
|
*/
|
||||||
|
public class SaAnnotationInterceptor implements Interceptor {
|
||||||
|
@Override
|
||||||
|
public void intercept(Invocation invocation) {
|
||||||
|
SaStrategy.me.checkMethodAnnotation.accept((invocation.getMethod()));
|
||||||
|
invocation.invoke();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,20 @@
|
|||||||
|
package cn.dev33.satoken.jfinal;
|
||||||
|
|
||||||
|
import com.jfinal.core.Controller;
|
||||||
|
|
||||||
|
public class SaControllerContext {
|
||||||
|
private static ThreadLocal<Controller> controllers = new ThreadLocal<>();
|
||||||
|
|
||||||
|
|
||||||
|
public static void hold(Controller controller) {
|
||||||
|
controllers.set(controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Controller get() {
|
||||||
|
return controllers.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void release() {
|
||||||
|
controllers.remove();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,70 @@
|
|||||||
|
package cn.dev33.satoken.jfinal;
|
||||||
|
|
||||||
|
import com.jfinal.kit.LogKit;
|
||||||
|
import com.jfinal.plugin.redis.serializer.ISerializer;
|
||||||
|
import com.jfinal.plugin.redis.serializer.JdkSerializer;
|
||||||
|
import redis.clients.jedis.util.SafeEncoder;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.ObjectInputStream;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
|
||||||
|
public class SaJdkSerializer implements ISerializer {
|
||||||
|
|
||||||
|
public static final ISerializer me = new JdkSerializer();
|
||||||
|
|
||||||
|
public byte[] keyToBytes(String key) {
|
||||||
|
return SafeEncoder.encode(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String keyFromBytes(byte[] bytes) {
|
||||||
|
return SafeEncoder.encode(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] fieldToBytes(Object field) {
|
||||||
|
return valueToBytes(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object fieldFromBytes(byte[] bytes) {
|
||||||
|
return valueFromBytes(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] valueToBytes(Object value) {
|
||||||
|
ObjectOutputStream objectOut = null;
|
||||||
|
try {
|
||||||
|
ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(1024);
|
||||||
|
objectOut = new ObjectOutputStream(bytesOut);
|
||||||
|
objectOut.writeObject(value);
|
||||||
|
objectOut.flush();
|
||||||
|
return bytesOut.toByteArray();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if(objectOut != null)
|
||||||
|
try {objectOut.close();} catch (Exception e) {
|
||||||
|
LogKit.error(e.getMessage(), e);}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object valueFromBytes(byte[] bytes) {
|
||||||
|
if(bytes == null || bytes.length == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
ObjectInputStream objectInput = null;
|
||||||
|
try {
|
||||||
|
ByteArrayInputStream bytesInput = new ByteArrayInputStream(bytes);
|
||||||
|
objectInput = new ObjectInputStream(bytesInput);
|
||||||
|
return objectInput.readObject();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if (objectInput != null)
|
||||||
|
try {objectInput.close();} catch (Exception e) {LogKit.error(e.getMessage(), e);}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,156 @@
|
|||||||
|
package cn.dev33.satoken.jfinal;
|
||||||
|
|
||||||
|
import com.jfinal.aop.Invocation;
|
||||||
|
import com.jfinal.config.Constants;
|
||||||
|
import com.jfinal.core.*;
|
||||||
|
import com.jfinal.kit.ReflectKit;
|
||||||
|
import com.jfinal.log.Log;
|
||||||
|
import com.jfinal.render.Render;
|
||||||
|
import com.jfinal.render.RenderException;
|
||||||
|
import com.jfinal.render.RenderManager;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
|
||||||
|
public class SaTokenActionHandler extends ActionHandler {
|
||||||
|
protected boolean devMode;
|
||||||
|
protected ActionMapping actionMapping;
|
||||||
|
protected ControllerFactory controllerFactory;
|
||||||
|
protected ActionReporter actionReporter;
|
||||||
|
protected static final RenderManager renderManager = RenderManager.me();
|
||||||
|
private static final Log log = Log.getLog(ActionHandler.class);
|
||||||
|
|
||||||
|
protected void init(ActionMapping actionMapping, Constants constants) {
|
||||||
|
this.actionMapping = actionMapping;
|
||||||
|
this.devMode = constants.getDevMode();
|
||||||
|
this.controllerFactory = constants.getControllerFactory();
|
||||||
|
this.actionReporter = constants.getActionReporter();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子类覆盖 getAction 方法可以定制路由功能
|
||||||
|
*/
|
||||||
|
protected Action getAction(String target, String[] urlPara) {
|
||||||
|
return actionMapping.getAction(target, urlPara);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {
|
||||||
|
if (target.indexOf('.') != -1) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
isHandled[0] = true;
|
||||||
|
String[] urlPara = {null};
|
||||||
|
Action action = getAction(target, urlPara);
|
||||||
|
|
||||||
|
if (action == null) {
|
||||||
|
if (log.isWarnEnabled()) {
|
||||||
|
String qs = request.getQueryString();
|
||||||
|
log.warn("404 Action Not Found: " + (qs == null ? target : target + "?" + qs));
|
||||||
|
}
|
||||||
|
renderManager.getRenderFactory().getErrorRender(404).setContext(request, response).render();
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller controller = null;
|
||||||
|
try {
|
||||||
|
// Controller controller = action.getControllerClass().newInstance();
|
||||||
|
controller = controllerFactory.getController(action.getControllerClass());
|
||||||
|
CPI._init_(controller, action, request, response, urlPara[0]);
|
||||||
|
//加入SaToken上下文处理
|
||||||
|
SaControllerContext.hold(controller);
|
||||||
|
|
||||||
|
if (devMode) {
|
||||||
|
if (actionReporter.isReportAfterInvocation(request)) {
|
||||||
|
new Invocation(action, controller).invoke();
|
||||||
|
actionReporter.report(target, controller, action);
|
||||||
|
} else {
|
||||||
|
actionReporter.report(target, controller, action);
|
||||||
|
new Invocation(action, controller).invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
new Invocation(action, controller).invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
Render render = controller.getRender();
|
||||||
|
if (render instanceof ForwardActionRender) {
|
||||||
|
String actionUrl = ((ForwardActionRender)render).getActionUrl();
|
||||||
|
if (target.equals(actionUrl)) {
|
||||||
|
throw new RuntimeException("The forward action url is the same as before.");
|
||||||
|
} else {
|
||||||
|
handle(actionUrl, request, response, isHandled);
|
||||||
|
}
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (render == null) {
|
||||||
|
render = renderManager.getRenderFactory().getDefaultRender(action.getViewPath() + action.getMethodName());
|
||||||
|
}
|
||||||
|
render.setContext(request, response, action.getViewPath()).render();
|
||||||
|
}
|
||||||
|
catch (RenderException e) {
|
||||||
|
if (log.isErrorEnabled()) {
|
||||||
|
String qs = request.getQueryString();
|
||||||
|
log.error(qs == null ? target : target + "?" + qs, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ActionException e) {
|
||||||
|
handleActionException(target, request, response, action, e);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
if (log.isErrorEnabled()) {
|
||||||
|
String qs = request.getQueryString();
|
||||||
|
String targetInfo = (qs == null ? target : target + "?" + qs);
|
||||||
|
String sign = ReflectKit.getMethodSignature(action.getMethod());
|
||||||
|
log.error(sign + " : " + targetInfo, e);
|
||||||
|
}
|
||||||
|
renderManager.getRenderFactory().getErrorRender(500).setContext(request, response, action.getViewPath()).render();
|
||||||
|
} finally {
|
||||||
|
SaControllerContext.release();
|
||||||
|
controllerFactory.recycle(controller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 抽取出该方法是为了缩短 handle 方法中的代码量,确保获得 JIT 优化,
|
||||||
|
* 方法长度超过 8000 个字节码时,将不会被 JIT 编译成二进制码
|
||||||
|
*
|
||||||
|
* 通过开启 java 的 -XX:+PrintCompilation 启动参数得知,handle(...)
|
||||||
|
* 方法(73 行代码)已被 JIT 优化,优化后的字节码长度为 593 个字节,相当于
|
||||||
|
* 每行代码产生 8.123 个字节
|
||||||
|
*/
|
||||||
|
private void handleActionException(String target, HttpServletRequest request, HttpServletResponse response, Action action, ActionException e) {
|
||||||
|
int errorCode = e.getErrorCode();
|
||||||
|
String msg = null;
|
||||||
|
if (errorCode == 404) {
|
||||||
|
msg = "404 Not Found: ";
|
||||||
|
} else if (errorCode == 400) {
|
||||||
|
msg = "400 Bad Request: ";
|
||||||
|
} else if (errorCode == 401) {
|
||||||
|
msg = "401 Unauthorized: ";
|
||||||
|
} else if (errorCode == 403) {
|
||||||
|
msg = "403 Forbidden: ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg != null) {
|
||||||
|
if (log.isWarnEnabled()) {
|
||||||
|
String qs = request.getQueryString();
|
||||||
|
msg = msg + (qs == null ? target : target + "?" + qs);
|
||||||
|
if (e.getMessage() != null) {
|
||||||
|
msg = msg + "\n" + e.getMessage();
|
||||||
|
}
|
||||||
|
log.warn(msg);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (log.isErrorEnabled()) {
|
||||||
|
String qs = request.getQueryString();
|
||||||
|
log.error(errorCode + " Error: " + (qs == null ? target : target + "?" + qs), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
e.getErrorRender().setContext(request, response, action.getViewPath()).render();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,51 @@
|
|||||||
|
package cn.dev33.satoken.jfinal;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.context.SaTokenContext;
|
||||||
|
import cn.dev33.satoken.context.model.SaRequest;
|
||||||
|
import cn.dev33.satoken.context.model.SaResponse;
|
||||||
|
import cn.dev33.satoken.context.model.SaStorage;
|
||||||
|
import cn.dev33.satoken.servlet.model.SaRequestForServlet;
|
||||||
|
import cn.dev33.satoken.servlet.model.SaResponseForServlet;
|
||||||
|
import cn.dev33.satoken.servlet.model.SaStorageForServlet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sa-Token 上线文处理器 [Jfinal 版本实现]
|
||||||
|
*/
|
||||||
|
public class SaTokenContextForJfinal implements SaTokenContext {
|
||||||
|
/**
|
||||||
|
* 获取当前请求的Request对象
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public SaRequest getRequest() {
|
||||||
|
return new SaRequestForServlet(SaControllerContext.get().getRequest());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前请求的Response对象
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public SaResponse getResponse() {
|
||||||
|
return new SaResponseForServlet(SaControllerContext.get().getResponse());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前请求的 [存储器] 对象
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public SaStorage getStorage() {
|
||||||
|
return new SaStorageForServlet(SaControllerContext.get().getRequest());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验指定路由匹配符是否可以匹配成功指定路径
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean matchPath(String pattern, String path) {
|
||||||
|
return PathAnalyzer.get(pattern).matches(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid() {
|
||||||
|
return SaTokenContext.super.isValid();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,286 @@
|
|||||||
|
package cn.dev33.satoken.jfinal;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.dao.SaTokenDao;
|
||||||
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
|
import com.jfinal.plugin.redis.Cache;
|
||||||
|
import com.jfinal.plugin.redis.Redis;
|
||||||
|
import com.jfinal.plugin.redis.serializer.ISerializer;
|
||||||
|
import redis.clients.jedis.Jedis;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class SaTokenDaoRedis implements SaTokenDao {
|
||||||
|
|
||||||
|
protected Cache redis;
|
||||||
|
protected ISerializer serializer;
|
||||||
|
/**
|
||||||
|
* 标记:是否已初始化成功
|
||||||
|
*/
|
||||||
|
public boolean isInit;
|
||||||
|
|
||||||
|
public SaTokenDaoRedis(String confName) {
|
||||||
|
redis = Redis.use(confName);
|
||||||
|
serializer = new SaJdkSerializer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Value,如无返空
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String get(String key) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
return jedis.get(key);
|
||||||
|
} finally {
|
||||||
|
close(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入Value,并设定存活时间 (单位: 秒)
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
* @param timeout
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void set(String key, String value, long timeout) {
|
||||||
|
if (timeout == 0 || timeout <= SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
if (timeout == SaTokenDao.NEVER_EXPIRE) {
|
||||||
|
jedis.set(key, value);
|
||||||
|
} else {
|
||||||
|
jedis.setex(key, timeout, value);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
close(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改指定key-value键值对 (过期时间不变)
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void update(String key, String value) {
|
||||||
|
long expire = getTimeout(key);
|
||||||
|
// -2 = 无此键
|
||||||
|
if (expire == SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.set(key, value, expire);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除Value
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void delete(String key) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
jedis.del(key);
|
||||||
|
} finally {
|
||||||
|
close(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Value的剩余存活时间 (单位: 秒)
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long getTimeout(String key) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
return jedis.ttl(key);
|
||||||
|
} finally {
|
||||||
|
close(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改Value的剩余存活时间 (单位: 秒)
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param timeout
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void updateTimeout(String key, long timeout) {
|
||||||
|
//判断是否想要设置为永久
|
||||||
|
if (timeout == SaTokenDao.NEVER_EXPIRE) {
|
||||||
|
long expire = getTimeout(key);
|
||||||
|
if (expire == SaTokenDao.NEVER_EXPIRE) {
|
||||||
|
// 如果其已经被设置为永久,则不作任何处理
|
||||||
|
} else {
|
||||||
|
// 如果尚未被设置为永久,那么再次set一次
|
||||||
|
this.set(key, this.get(key), timeout);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
jedis.expire(key, timeout);
|
||||||
|
} finally {
|
||||||
|
close(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Object,如无返空
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Object getObject(String key) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
return valueFromBytes(jedis.get(keyToBytes(key)));
|
||||||
|
} finally {
|
||||||
|
close(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入Object,并设定存活时间 (单位: 秒)
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param object
|
||||||
|
* @param timeout
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setObject(String key, Object object, long timeout) {
|
||||||
|
if (timeout == 0 || timeout <= SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
if (timeout == SaTokenDao.NEVER_EXPIRE) {
|
||||||
|
jedis.set(keyToBytes(key), valueToBytes(object));
|
||||||
|
} else {
|
||||||
|
jedis.setex(keyToBytes(key), timeout, valueToBytes(object));
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
close(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新Object (过期时间不变)
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param object
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void updateObject(String key, Object object) {
|
||||||
|
long expire = getObjectTimeout(key);
|
||||||
|
// -2 = 无此键
|
||||||
|
if (expire == SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.setObject(key, object, expire);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除Object
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void deleteObject(String key) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
jedis.del(keyToBytes(key));
|
||||||
|
} finally {
|
||||||
|
close(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getObjectTimeout(String key) {
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
return jedis.ttl(keyToBytes(key));
|
||||||
|
} finally {
|
||||||
|
close(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改Object的剩余存活时间 (单位: 秒)
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param timeout
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void updateObjectTimeout(String key, long timeout) {
|
||||||
|
//判断是否想要设置为永久
|
||||||
|
if (timeout == SaTokenDao.NEVER_EXPIRE) {
|
||||||
|
long expire = getObjectTimeout(key);
|
||||||
|
if (expire == SaTokenDao.NEVER_EXPIRE) {
|
||||||
|
// 如果其已经被设置为永久,则不作任何处理
|
||||||
|
} else {
|
||||||
|
// 如果尚未被设置为永久,那么再次set一次
|
||||||
|
this.setObject(key, this.getObject(key), timeout);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Jedis jedis = getJedis();
|
||||||
|
try {
|
||||||
|
jedis.expire(keyToBytes(key), timeout);
|
||||||
|
} finally {
|
||||||
|
close(jedis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索数据
|
||||||
|
*
|
||||||
|
* @param prefix
|
||||||
|
* @param keyword
|
||||||
|
* @param start
|
||||||
|
* @param size
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<String> searchData(String prefix, String keyword, int start, int size) {
|
||||||
|
Set<String> keys = redis.keys(prefix + "*" + keyword + "*");
|
||||||
|
List<String> list = new ArrayList<String>(keys);
|
||||||
|
return SaFoxUtil.searchList(list, start, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Jedis getJedis() {
|
||||||
|
return redis.getJedis();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close(Jedis jedis) {
|
||||||
|
if (jedis != null)
|
||||||
|
jedis.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected byte[] keyToBytes(Object key) {
|
||||||
|
return key.toString().getBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected byte[] valueToBytes(Object value) {
|
||||||
|
return serializer.valueToBytes(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object valueFromBytes(byte[] bytes) {
|
||||||
|
return serializer.valueFromBytes(bytes);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,154 @@
|
|||||||
|
package cn.dev33.satoken.jfinal;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.exception.SaTokenException;
|
||||||
|
import cn.dev33.satoken.filter.SaFilterAuthStrategy;
|
||||||
|
import cn.dev33.satoken.filter.SaFilterErrorStrategy;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SaTokenPathFilter {
|
||||||
|
|
||||||
|
// ------------------------ 设置此过滤器 拦截 & 放行 的路由
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拦截路由
|
||||||
|
*/
|
||||||
|
private List<String> includeList = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 放行路由
|
||||||
|
*/
|
||||||
|
private List<String> excludeList = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加 [拦截路由]
|
||||||
|
* @param paths 路由
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaTokenPathFilter addInclude(String... paths) {
|
||||||
|
includeList.addAll(Arrays.asList(paths));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加 [放行路由]
|
||||||
|
* @param paths 路由
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaTokenPathFilter addExclude(String... paths) {
|
||||||
|
excludeList.addAll(Arrays.asList(paths));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入 [拦截路由] 集合
|
||||||
|
* @param pathList 路由集合
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaTokenPathFilter setIncludeList(List<String> pathList) {
|
||||||
|
includeList = pathList;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入 [放行路由] 集合
|
||||||
|
* @param pathList 路由集合
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaTokenPathFilter setExcludeList(List<String> pathList) {
|
||||||
|
excludeList = pathList;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [拦截路由] 集合
|
||||||
|
* @return see note
|
||||||
|
*/
|
||||||
|
public List<String> getIncludeList() {
|
||||||
|
return includeList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [放行路由] 集合
|
||||||
|
* @return see note
|
||||||
|
*/
|
||||||
|
public List<String> getExcludeList() {
|
||||||
|
return excludeList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------ 钩子函数
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 认证函数:每次请求执行
|
||||||
|
*/
|
||||||
|
public SaFilterAuthStrategy auth = r -> {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常处理函数:每次[认证函数]发生异常时执行此函数
|
||||||
|
*/
|
||||||
|
public SaFilterErrorStrategy error = e -> {
|
||||||
|
throw new SaTokenException(e);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前置函数:在每次[认证函数]之前执行
|
||||||
|
*/
|
||||||
|
public SaFilterAuthStrategy beforeAuth = r -> {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入[认证函数]: 每次请求执行
|
||||||
|
* @param auth see note
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaTokenPathFilter setAuth(SaFilterAuthStrategy auth) {
|
||||||
|
this.auth = auth;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入[异常处理函数]:每次[认证函数]发生异常时执行此函数
|
||||||
|
* @param error see note
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaTokenPathFilter setError(SaFilterErrorStrategy error) {
|
||||||
|
this.error = error;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入[前置函数]:在每次[认证函数]之前执行
|
||||||
|
* @param beforeAuth see note
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaTokenPathFilter setBeforeAuth(SaFilterAuthStrategy beforeAuth) {
|
||||||
|
this.beforeAuth = beforeAuth;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*@Override
|
||||||
|
public void doFilter(Controller ctx, FilterChain chain) throws Throwable {
|
||||||
|
try {
|
||||||
|
// 执行全局过滤器
|
||||||
|
SaRouter.match(includeList).notMatch(excludeList).check(r -> {
|
||||||
|
beforeAuth.run(null);
|
||||||
|
auth.run(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (StopMatchException e) {
|
||||||
|
|
||||||
|
} catch (Throwable e) {
|
||||||
|
// 1. 获取异常处理策略结果
|
||||||
|
String result = (e instanceof BackResultException) ? e.getMessage() : String.valueOf(error.run(e));
|
||||||
|
// 2. 写入输出流
|
||||||
|
ctx.renderText(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行
|
||||||
|
chain.doFilter(ctx);
|
||||||
|
}*/
|
||||||
|
}
|
@@ -0,0 +1,38 @@
|
|||||||
|
package cn.dev33.satoken.jfinal.test;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import com.jfinal.core.Controller;
|
||||||
|
import com.jfinal.core.Path;
|
||||||
|
import com.jfinal.server.undertow.UndertowServer;
|
||||||
|
|
||||||
|
@Path("/")
|
||||||
|
public class AppRun extends Controller {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
UndertowServer.create(Config.class)
|
||||||
|
.addHotSwapClassPrefix("cn.dev33.satoken.jfinal.")
|
||||||
|
.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void index(){
|
||||||
|
renderText("index");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doLogin(){
|
||||||
|
StpUtil.logout();
|
||||||
|
StpUtil.login(10002);
|
||||||
|
//赋值角色
|
||||||
|
renderText("登录成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getLoginInfo(){
|
||||||
|
System.out.println("是否登录:"+StpUtil.isLogin());
|
||||||
|
System.out.println("登录信息"+StpUtil.getTokenInfo());
|
||||||
|
renderJson(StpUtil.getTokenInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SaCheckRole("super-admin")
|
||||||
|
public void add(){
|
||||||
|
renderText("超级管理员方法!");
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,86 @@
|
|||||||
|
package cn.dev33.satoken.jfinal.test;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.SaManager;
|
||||||
|
import cn.dev33.satoken.config.SaCookieConfig;
|
||||||
|
import cn.dev33.satoken.config.SaTokenConfig;
|
||||||
|
import cn.dev33.satoken.context.SaTokenContext;
|
||||||
|
import cn.dev33.satoken.jfinal.*;
|
||||||
|
import cn.dev33.satoken.util.SaTokenConsts;
|
||||||
|
import com.jfinal.config.*;
|
||||||
|
import com.jfinal.plugin.redis.RedisPlugin;
|
||||||
|
import com.jfinal.plugin.redis.serializer.ISerializer;
|
||||||
|
import com.jfinal.template.Engine;
|
||||||
|
|
||||||
|
public class Config extends JFinalConfig {
|
||||||
|
|
||||||
|
public Config(){
|
||||||
|
//注册权限验证功能,由saToken处理请求上下文
|
||||||
|
SaTokenContext saTokenContext = new SaTokenContextForJfinal();
|
||||||
|
SaManager.setSaTokenContext(saTokenContext);
|
||||||
|
//加载权限角色设置数据接口
|
||||||
|
SaManager.setStpInterface(new StpInterfaceImpl());
|
||||||
|
//设置token生成类型
|
||||||
|
SaTokenConfig saTokenConfig = new SaTokenConfig();
|
||||||
|
saTokenConfig.setTokenStyle(SaTokenConsts.TOKEN_STYLE_SIMPLE_UUID);
|
||||||
|
saTokenConfig.setTimeout(60*60*4); //登录有效时间4小时
|
||||||
|
saTokenConfig.setActivityTimeout(30*60); //半小时无操作过期处理
|
||||||
|
saTokenConfig.setIsShare(false);
|
||||||
|
saTokenConfig.setTokenName("token"); //更改satoken的cookies名称
|
||||||
|
SaCookieConfig saCookieConfig = new SaCookieConfig();
|
||||||
|
saCookieConfig.setHttpOnly(true); //开启cookies 的httponly属性
|
||||||
|
saTokenConfig.setCookie(saCookieConfig);
|
||||||
|
SaManager.setConfig(saTokenConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configConstant(Constants constants) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configRoute(Routes routes) {
|
||||||
|
//路由扫描
|
||||||
|
routes.scan("cn.dev33.satoken.jfinal");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configEngine(Engine engine) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configPlugin(Plugins plugins) {
|
||||||
|
//添加redis扩展
|
||||||
|
plugins.add(createRedisPlugin("satoken",1, SaJdkSerializer.me));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configInterceptor(Interceptors interceptors) {
|
||||||
|
//开启注解方式权限验证
|
||||||
|
interceptors.add(new SaAnnotationInterceptor());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configHandler(Handlers handlers) {
|
||||||
|
//将上下文交给satoken处理
|
||||||
|
handlers.setActionHandler(new SaTokenActionHandler());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建Redis插件
|
||||||
|
* @param name 名称
|
||||||
|
* @param dbIndex 使用的库ID
|
||||||
|
* @param serializer 自定义序列化方法
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private RedisPlugin createRedisPlugin(String name, Integer dbIndex, ISerializer serializer) {
|
||||||
|
RedisPlugin redisPlugin = new RedisPlugin(name, "redis-host", 6379, 3000,"pwd",dbIndex);
|
||||||
|
redisPlugin.setSerializer(serializer);
|
||||||
|
return redisPlugin;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onStart(){
|
||||||
|
//增加redis缓存,需要先配置redis地址
|
||||||
|
SaManager.setSaTokenDao(new SaTokenDaoRedis("satoken"));
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,21 @@
|
|||||||
|
package cn.dev33.satoken.jfinal.test;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.StpInterface;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class StpInterfaceImpl implements StpInterface {
|
||||||
|
@Override
|
||||||
|
public List<String> getPermissionList(Object o, String s) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getRoleList(Object o, String s) {
|
||||||
|
List<String> list = new ArrayList<String>();
|
||||||
|
list.add("admin");
|
||||||
|
list.add("super-admin");
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user