diff --git a/doc/db/boot_security.sql b/doc/db/boot_security.sql index 1cc36a36f34e6f5889e9cf4882115e8d10e081b6..3071eb96a105573c1fe155687c9acd481b38e40e 100644 --- a/doc/db/boot_security.sql +++ b/doc/db/boot_security.sql @@ -542,3 +542,15 @@ CREATE TABLE `t_notice_read` ( -- ---------------------------- -- Records of t_notice_read -- ---------------------------- +-- ---------------------------- +-- Table structure for t_token +-- ---------------------------- +DROP TABLE IF EXISTS `t_token`; +CREATE TABLE `t_token` ( + `id` varchar(36) NOT NULL COMMENT 'token', + `val` text NOT NULL COMMENT 'LoginUser的json串', + `expireTime` datetime NOT NULL, + `createTime` datetime NOT NULL, + `updateTime` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file diff --git "a/doc/\346\241\206\346\236\266\345\217\212\351\205\215\347\275\256.docx" "b/doc/\346\241\206\346\236\266\345\217\212\351\205\215\347\275\256.docx" index 3d4701d8de562386269886afb6b3d70585f057c0..4e8ba32e5a246a8628fea8f1af533d08f8d0ec0b 100644 Binary files "a/doc/\346\241\206\346\236\266\345\217\212\351\205\215\347\275\256.docx" and "b/doc/\346\241\206\346\236\266\345\217\212\351\205\215\347\275\256.docx" differ diff --git a/src/main/java/com/boot/security/server/dao/TokenDao.java b/src/main/java/com/boot/security/server/dao/TokenDao.java new file mode 100644 index 0000000000000000000000000000000000000000..9bdf37f764eeafe3474314b4b0a1a1185edf4829 --- /dev/null +++ b/src/main/java/com/boot/security/server/dao/TokenDao.java @@ -0,0 +1,25 @@ +package com.boot.security.server.dao; + +import org.apache.ibatis.annotations.Delete; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; + +import com.boot.security.server.model.TokenModel; + +@Mapper +public interface TokenDao { + + @Insert("insert into t_token(id, val, expireTime, createTime, updateTime) values (#{id}, #{val}, #{expireTime}, #{createTime}, #{updateTime})") + int save(TokenModel model); + + @Select("select * from t_token t where t.id = #{id}") + TokenModel getById(String id); + + @Update("update t_token t set t.val = #{val}, t.expireTime = #{expireTime}, t.updateTime = #{updateTime} where t.id = #{id}") + int update(TokenModel model); + + @Delete("delete from t_token where id = #{id}") + int delete(String id); +} diff --git a/src/main/java/com/boot/security/server/dto/LoginUser.java b/src/main/java/com/boot/security/server/dto/LoginUser.java index 9b2a4814e8542329021fb7a26f905d160b656568..d1bf792d2a2be20d5dd4311eb05e0fb434a9cf35 100644 --- a/src/main/java/com/boot/security/server/dto/LoginUser.java +++ b/src/main/java/com/boot/security/server/dto/LoginUser.java @@ -47,6 +47,10 @@ public class LoginUser extends SysUser implements UserDetails { .map(p -> new SimpleGrantedAuthority(p.getPermission())).collect(Collectors.toSet()); } + public void setAuthorities(Collection authorities) { + // do nothing + } + // 账户是否未过期 @JsonIgnore @Override diff --git a/src/main/java/com/boot/security/server/model/TokenModel.java b/src/main/java/com/boot/security/server/model/TokenModel.java new file mode 100644 index 0000000000000000000000000000000000000000..79bc28af65e90ddc59c3994833f8467ca9a3c759 --- /dev/null +++ b/src/main/java/com/boot/security/server/model/TokenModel.java @@ -0,0 +1,34 @@ +package com.boot.security.server.model; + +import java.util.Date; + +public class TokenModel extends BaseEntity { + + private static final long serialVersionUID = 4566334160572911795L; + + /** + * 过期时间 + */ + private Date expireTime; + /** + * LoginUser的json串 + */ + private String val; + + public Date getExpireTime() { + return expireTime; + } + + public void setExpireTime(Date expireTime) { + this.expireTime = expireTime; + } + + public String getVal() { + return val; + } + + public void setVal(String val) { + this.val = val; + } + +} diff --git a/src/main/java/com/boot/security/server/service/TokenService.java b/src/main/java/com/boot/security/server/service/TokenService.java index 6b1dc98168e115083d949a97cb67d4fe86facbf5..9c68e399d3a1e7d1be5bcfdf7c2d6be447af48cb 100644 --- a/src/main/java/com/boot/security/server/service/TokenService.java +++ b/src/main/java/com/boot/security/server/service/TokenService.java @@ -4,7 +4,12 @@ import com.boot.security.server.dto.LoginUser; import com.boot.security.server.dto.Token; /** - * Token管理器 + * Token管理器
+ * 可存储到redis或者数据库
+ * 具体可看实现类
+ * 默认基于redis,实现类为 com.boot.security.server.service.impl.TokenServiceImpl
+ * 如要换成数据库存储,将TokenServiceImpl类上的注解@Primary挪到com.boot.security.server.service.impl.TokenServiceDbImpl + * * * @author 小威老师 * diff --git a/src/main/java/com/boot/security/server/service/impl/TokenServiceDbImpl.java b/src/main/java/com/boot/security/server/service/impl/TokenServiceDbImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..697ebfbc07048b86072ab2ddd00bc0cf74caeaee --- /dev/null +++ b/src/main/java/com/boot/security/server/service/impl/TokenServiceDbImpl.java @@ -0,0 +1,99 @@ +package com.boot.security.server.service.impl; + +import java.util.Date; +import java.util.UUID; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import com.alibaba.fastjson.JSONObject; +import com.boot.security.server.dao.TokenDao; +import com.boot.security.server.dto.LoginUser; +import com.boot.security.server.dto.Token; +import com.boot.security.server.model.TokenModel; +import com.boot.security.server.service.SysLogService; +import com.boot.security.server.service.TokenService; + +/** + * token存到数据库的实现类 + * + * @author 小威老师 + * + */ +@Service +public class TokenServiceDbImpl implements TokenService { + + /** + * token过期秒数 + */ + @Value("${token.expire.seconds}") + private Integer expireSeconds; + @Autowired + private TokenDao tokenDao; + @Autowired + private SysLogService logService; + + @Override + public Token saveToken(LoginUser loginUser) { + String token = UUID.randomUUID().toString(); + + loginUser.setToken(token); + loginUser.setLoginTime(System.currentTimeMillis()); + loginUser.setExpireTime(loginUser.getLoginTime() + expireSeconds * 1000); + + TokenModel model = new TokenModel(); + model.setId(token); + model.setCreateTime(new Date()); + model.setUpdateTime(new Date()); + model.setExpireTime(new Date(loginUser.getExpireTime())); + model.setVal(JSONObject.toJSONString(loginUser)); + + tokenDao.save(model); + // 登陆日志 + logService.save(loginUser.getId(), "登陆", true, null); + + return new Token(token, loginUser.getLoginTime()); + } + + @Override + public void refresh(LoginUser loginUser) { + loginUser.setLoginTime(System.currentTimeMillis()); + loginUser.setExpireTime(loginUser.getLoginTime() + expireSeconds * 1000); + + TokenModel model = tokenDao.getById(loginUser.getToken()); + model.setUpdateTime(new Date()); + model.setExpireTime(new Date(loginUser.getExpireTime())); + model.setVal(JSONObject.toJSONString(loginUser)); + + tokenDao.update(model); + } + + @Override + public LoginUser getLoginUser(String token) { + TokenModel model = tokenDao.getById(token); + return toLoginUser(model); + } + + @Override + public boolean deleteToken(String token) { + TokenModel model = tokenDao.getById(token); + LoginUser loginUser = toLoginUser(model); + if (loginUser != null) { + tokenDao.delete(token); + logService.save(loginUser.getId(), "退出", true, null); + + return true; + } + + return false; + } + + private LoginUser toLoginUser(TokenModel model) { + if (model == null) { + return null; + } + return JSONObject.parseObject(model.getVal(), LoginUser.class); + } + +} diff --git a/src/main/java/com/boot/security/server/service/impl/TokenServiceImpl.java b/src/main/java/com/boot/security/server/service/impl/TokenServiceImpl.java index ef92d9b4b31419f872f6f0d0cfab8afc21b887b2..968a4c20bb5a4fbeb93e73f221df39283b913323 100644 --- a/src/main/java/com/boot/security/server/service/impl/TokenServiceImpl.java +++ b/src/main/java/com/boot/security/server/service/impl/TokenServiceImpl.java @@ -5,6 +5,7 @@ import java.util.concurrent.TimeUnit; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Primary; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; @@ -13,6 +14,13 @@ import com.boot.security.server.dto.Token; import com.boot.security.server.service.SysLogService; import com.boot.security.server.service.TokenService; +/** + * token存到redis的实现类 + * + * @author 小威老师 + * + */ +@Primary @Service public class TokenServiceImpl implements TokenService {