From efbed347c8b659ca13207a1dbe34e77fdb003949 Mon Sep 17 00:00:00 2001
From: XiaoRuby <3114200645@qq.com>
Date: 星期五, 07 七月 2023 16:40:32 +0800
Subject: [PATCH] LIMS管理系统框架-开发-1.0.0
---
user-server/src/main/java/com/yuanchu/limslaboratory/pojo/Role.java | 15
user-server/src/main/java/com/yuanchu/limslaboratory/pojo/User.java | 28 +
user-server/src/main/java/com/yuanchu/limslaboratory/shiro/filter/JwtFilter.java | 170 ++++++++++
user-server/src/main/java/com/yuanchu/limslaboratory/shiro/realm/ShiroRealm.java | 55 +++
user-server/src/main/java/com/yuanchu/limslaboratory/shiro/config/ShiroConfig.java | 167 ++++++++++
user-server/src/main/java/com/yuanchu/limslaboratory/clients/UserLoginUtils.java | 39 +-
user-server/src/main/java/com/yuanchu/limslaboratory/pojo/EnterpriseUserList.java | 15
user-server/src/main/java/com/yuanchu/limslaboratory/shiro/JwtToken.java | 28 +
pom.xml | 8
user-server/src/main/java/com/yuanchu/limslaboratory/shiro/utils/JwtCredentialsMatcher.java | 34 ++
/dev/null | 5
framework/src/main/java/com/yuanchu/limslaboratory/config/WebMvcConfig.java | 16
user-server/src/main/java/com/yuanchu/limslaboratory/service/impl/UserServiceImpl.java | 12
user-server/src/main/java/com/yuanchu/limslaboratory/shiro/MultiRealmAuthenticator.java | 61 +++
user-server/src/main/java/com/yuanchu/limslaboratory/controller/UserController.java | 48 ++
user-server/src/main/java/com/yuanchu/limslaboratory/pojo/Enterprise.java | 17
user-server/src/main/java/com/yuanchu/limslaboratory/shiro/realm/JwtRealm.java | 57 +++
user-server/pom.xml | 6
user-server/src/main/java/com/yuanchu/limslaboratory/shiro/utils/JwtUtils.java | 160 ++++++++++
user-server/src/main/java/com/yuanchu/limslaboratory/service/UserService.java | 3
20 files changed, 893 insertions(+), 51 deletions(-)
diff --git a/framework/src/main/java/com/yuanchu/limslaboratory/config/WebMvcConfig.java b/framework/src/main/java/com/yuanchu/limslaboratory/config/WebMvcConfig.java
index 560b57f..64012d1 100644
--- a/framework/src/main/java/com/yuanchu/limslaboratory/config/WebMvcConfig.java
+++ b/framework/src/main/java/com/yuanchu/limslaboratory/config/WebMvcConfig.java
@@ -1,23 +1,27 @@
package com.yuanchu.limslaboratory.config;
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Configuration;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import java.io.File;
+import java.util.List;
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
- // swagger鍙鍖栭厤缃�
- registry.addResourceHandler("/systemPictures/**")
- .addResourceLocations("file:" + System.getProperty("user.dir")+ File.separator+"uploadFile"+File.separator+"systemPictures"+File.separator);
- registry.addResourceHandler("/uploadFile/pluginFiles/logo/**")
- .addResourceLocations("file:" + System.getProperty("user.dir")+ File.separator+"uploadFile"+File.separator+"pluginFiles"+File.separator+"logo"+File.separator);
-
+ //閰嶇疆鎷︽埅鍣ㄨ闂潤鎬佽祫婧�
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
+ registry.addResourceHandler("/favicon.ico").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
//璁剧疆鏂囦欢铏氭嫙璺緞鏄犲皠
diff --git a/framework/src/main/java/com/yuanchu/limslaboratory/utils/JwtUtils.java b/framework/src/main/java/com/yuanchu/limslaboratory/utils/JwtUtils.java
deleted file mode 100644
index 34eaa8e..0000000
--- a/framework/src/main/java/com/yuanchu/limslaboratory/utils/JwtUtils.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.yuanchu.limslaboratory.utils;
-
-
-import com.auth0.jwt.JWT;
-import com.auth0.jwt.algorithms.Algorithm;
-import com.auth0.jwt.exceptions.JWTCreationException;
-
-import java.util.Date;
-
-public class JwtUtils {
- // 杩囨湡鏃堕棿 2 灏忔椂
-// private static final long EXPIRE_TIME = 2 * 60 * 60 * 1000;
-
- private static final long EXPIRE_TIME = 10;
- /**
- * 鐢熸垚绛惧悕,鍑嗙‘鍦拌鏄敓鎴恡oken
- * @param secret
- * @return
- */
- public static String sign(String account, String secret){
- try{
- Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
- Algorithm algorithm = Algorithm.HMAC256(secret);
- //闄勫甫username,nickname淇℃伅
- return JWT.create()
- .withClaim("account",account)
- .withExpiresAt(date)
- .sign(algorithm);
- } catch (JWTCreationException e){
- e.printStackTrace();
- return null;
- } catch (Exception e){
- e.printStackTrace();
- return null;
- }
- }
-}
diff --git a/pom.xml b/pom.xml
index 6622ba9..580ba65 100644
--- a/pom.xml
+++ b/pom.xml
@@ -32,6 +32,7 @@
<mybatis-plus.version>3.4.0</mybatis-plus.version>
<openfeign.version>3.1.3</openfeign.version>
<feign-okhttp.version>11.0</feign-okhttp.version>
+ <shiro.version>1.5.3</shiro.version>
</properties>
<dependencies>
@@ -127,6 +128,13 @@
<artifactId>feign-okhttp</artifactId>
<version>${feign-okhttp.version}</version>
</dependency>
+
+ <!--瀹夊叏妗嗘灦shiro-->
+ <dependency>
+ <groupId>org.apache.shiro</groupId>
+ <artifactId>shiro-spring-boot-starter</artifactId>
+ <version>${shiro.version}</version>
+ </dependency>
</dependencies>
</dependencyManagement>
diff --git a/user-server/pom.xml b/user-server/pom.xml
index c0fd1c3..96c60be 100644
--- a/user-server/pom.xml
+++ b/user-server/pom.xml
@@ -43,6 +43,12 @@
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
+
+ <!--瀹夊叏妗嗘灦shiro-->
+ <dependency>
+ <groupId>org.apache.shiro</groupId>
+ <artifactId>shiro-spring-boot-starter</artifactId>
+ </dependency>
</dependencies>
</project>
diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/clients/UserLoginUtils.java b/user-server/src/main/java/com/yuanchu/limslaboratory/clients/UserLoginUtils.java
index 04dc927..b54743d 100644
--- a/user-server/src/main/java/com/yuanchu/limslaboratory/clients/UserLoginUtils.java
+++ b/user-server/src/main/java/com/yuanchu/limslaboratory/clients/UserLoginUtils.java
@@ -1,5 +1,8 @@
package com.yuanchu.limslaboratory.clients;
+import com.yuanchu.limslaboratory.pojo.User;
+import com.yuanchu.limslaboratory.shiro.utils.JwtUtils;
+import com.yuanchu.limslaboratory.utils.RedisUtil;
import com.yuanchu.limslaboratory.vo.Result;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@@ -19,6 +22,7 @@
@Value("${login.secret}")
private String LoginSecret;
+
// public Result<Map<String, Object>> LoginExamine(User user){
// Map<String, Object> mapData = new HashMap<>();
// mapData.put("LoginUserID", LoginUserID);
@@ -30,7 +34,7 @@
// Map data = (Map) result.getData();
// String token = data.get("token").toString();
// data.remove("token");
-// user.setMap(data);
+//// user.setMap(data);
// //瀛樺叆redis,浜屼釜灏忔椂鍚庡垹闄�
// RedisUtil.set(token, user, 2);
// // 灏嗙鍙戠殑 JWT token 杩斿洖缁欏墠绔�
@@ -48,26 +52,17 @@
// }
// }
- public Result<Map<String, Object>> LoginExamine(){
- Map<String, Object> mapData = new HashMap<>();
- mapData.put("LoginUserID", LoginUserID);
- mapData.put("LoginSecret", LoginSecret);
- Result<?> code = userClient.BusynessUserLogin(mapData);
- if (code.getCode() == 200){
- Result<?> result = userClient.BusynessUserLoginToken(code.getData().toString());
- if (result.getCode() == 200){
- Map data = (Map) result.getData();
- String token = data.get("token").toString();
- data.remove("token");
- // 灏嗙鍙戠殑 JWT token 杩斿洖缁欏墠绔�
- HashMap<String, Object> map = new HashMap<>();
- map.put("token", token);
- return Result.success(map);
- } else {
- return Result.fail(result.getMessage());
- }
- } else {
- return Result.fail(code.getMessage());
- }
+
+ public Result<Map<String, Object>> LoginExamine(User user){
+ String token = JwtUtils.sign(user.getAccount());
+ //瀛樺叆redis,浜屼釜灏忔椂鍚庡垹闄�
+ RedisUtil.set(token, user, 2);
+ // 灏嗙鍙戠殑 JWT token 杩斿洖缁欏墠绔�
+ HashMap<String, Object> map = new HashMap<>();
+ String refresh = JwtUtils.sign(user.getAccount());
+ map.put("token", token);
+ map.put("refresh", refresh);
+ RedisUtil.set(user.getAccount(), map, 120);
+ return Result.success(map);
}
}
diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/controller/UserController.java b/user-server/src/main/java/com/yuanchu/limslaboratory/controller/UserController.java
index 5bb5aca..b2eaf01 100644
--- a/user-server/src/main/java/com/yuanchu/limslaboratory/controller/UserController.java
+++ b/user-server/src/main/java/com/yuanchu/limslaboratory/controller/UserController.java
@@ -1,6 +1,20 @@
package com.yuanchu.limslaboratory.controller;
-
+import com.yuanchu.limslaboratory.clients.UserLoginUtils;
+import com.yuanchu.limslaboratory.pojo.User;
+import com.yuanchu.limslaboratory.shiro.realm.ShiroRealm;
+import com.yuanchu.limslaboratory.utils.SpringUtils;
+import com.yuanchu.limslaboratory.vo.Result;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authc.IncorrectCredentialsException;
+import org.apache.shiro.authc.UnknownAccountException;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.subject.Subject;
+import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -15,6 +29,38 @@
*/
@RestController
@RequestMapping("/user")
+@Api(tags = "鐢ㄦ埛妯″潡")
public class UserController {
+ @ApiOperation("鐢ㄦ埛鐧诲綍")
+ @ApiImplicitParams(value = {
+ @ApiImplicitParam(name = "account", value = "璐﹀彿", dataTypeClass = String.class, required = true),
+ @ApiImplicitParam(name = "password", value = "瀵嗙爜", dataTypeClass = String.class, required = true)
+ })
+ @PostMapping("/login")
+ public Result<?> UserLogin(String account, String password){
+ boolean loginSuccess = false;
+ Subject subject = SecurityUtils.getSubject();
+ if (!subject.isAuthenticated()) {
+ UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(account, password);
+ try {
+ subject.login(usernamePasswordToken);
+ loginSuccess = true;
+ } catch (UnknownAccountException e) {
+ return Result.fail(202, "娌℃湁鎵惧埌璇ヨ处鍙凤紝璇锋鏌ヨ緭鍏ワ紒");
+ } catch (IncorrectCredentialsException e) {
+ return Result.fail(202, "瀵嗙爜涓嶅尮閰嶏紝璇锋鏌ヨ緭鍏ワ紒");
+ }
+ }
+ if (loginSuccess) {
+ // 鑾峰彇shiroRealm涓殑鏁版嵁
+ ShiroRealm bean = SpringUtils.getBean(ShiroRealm.class);
+ User user = bean.user;
+ user.setPassword(null);
+ UserLoginUtils bean1 = SpringUtils.getBean(UserLoginUtils.class);
+ return bean1.LoginExamine(user);
+ }else {
+ return Result.fail("鐧诲綍澶辫触");
+ }
+ }
}
diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/Enterprise.java b/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/Enterprise.java
index 175ba92..d3508b0 100644
--- a/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/Enterprise.java
+++ b/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/Enterprise.java
@@ -1,9 +1,14 @@
package com.yuanchu.limslaboratory.pojo;
+import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import java.io.Serializable;
+import java.util.Date;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -11,7 +16,7 @@
/**
* <p>
- *
+ *
* </p>
*
* @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
@@ -46,11 +51,13 @@
@ApiModelProperty(value = "鑱旂郴浜虹數璇�")
private String linkPhone;
- @ApiModelProperty(value = "鍒涘缓鏃堕棿")
- private LocalDateTime createTime;
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone="GMT+8")
+ private Date createTime;
- @ApiModelProperty(value = "鏇存柊鏃堕棿")
- private LocalDateTime updateTime;
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone="GMT+8")
+ private Date updateTime;
@ApiModelProperty(value = "閿�")
private Integer version;
diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/EnterpriseUserList.java b/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/EnterpriseUserList.java
index d1ed711..2950361 100644
--- a/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/EnterpriseUserList.java
+++ b/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/EnterpriseUserList.java
@@ -1,9 +1,14 @@
package com.yuanchu.limslaboratory.pojo;
+import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import java.io.Serializable;
+import java.util.Date;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -11,7 +16,7 @@
/**
* <p>
- *
+ *
* </p>
*
* @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
@@ -37,9 +42,13 @@
@ApiModelProperty(value = "0:鍒犻櫎;1:姝e父")
private Integer state;
- private LocalDateTime createTime;
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone="GMT+8")
+ private Date createTime;
- private LocalDateTime updateTime;
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone="GMT+8")
+ private Date updateTime;
private Integer version;
diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/Role.java b/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/Role.java
index 152fe60..cf2e20c 100644
--- a/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/Role.java
+++ b/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/Role.java
@@ -1,9 +1,14 @@
package com.yuanchu.limslaboratory.pojo;
+import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import java.io.Serializable;
+import java.util.Date;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -11,7 +16,7 @@
/**
* <p>
- *
+ *
* </p>
*
* @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
@@ -37,9 +42,13 @@
@ApiModelProperty(value = "閫昏緫鍒犻櫎 姝e父>=1,鍒犻櫎<=0")
private Integer state;
- private LocalDateTime createTime;
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone="GMT+8")
+ private Date createTime;
- private LocalDateTime updateTime;
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone="GMT+8")
+ private Date updateTime;
@ApiModelProperty(value = "涔愯閿�")
private Integer version;
diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/User.java b/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/User.java
index 34f3d2f..9ae5655 100644
--- a/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/User.java
+++ b/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/User.java
@@ -1,17 +1,25 @@
package com.yuanchu.limslaboratory.pojo;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.*;
+
import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.Date;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
+import net.sf.jsqlparser.expression.DateTimeLiteralExpression;
/**
* <p>
- *
+ *
* </p>
*
* @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
@@ -46,12 +54,20 @@
@ApiModelProperty(value = "骞撮緞")
private Integer age;
+ @TableLogic(value = "1", delval = "0")
@ApiModelProperty(value = "鍦ㄨ亴鐘舵�� 姝e父>=1,绂昏亴<=0")
private Integer jobState;
- private LocalDateTime createTime;
+ @ApiModelProperty(value = "涓�х鍚�")
+ private String info;
- private LocalDateTime updateTime;
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone="GMT+8")
+ private Date createTime;
+
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone="GMT+8")
+ private Date updateTime;
private Integer version;
diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/service/UserService.java b/user-server/src/main/java/com/yuanchu/limslaboratory/service/UserService.java
index ff42a44..674166d 100644
--- a/user-server/src/main/java/com/yuanchu/limslaboratory/service/UserService.java
+++ b/user-server/src/main/java/com/yuanchu/limslaboratory/service/UserService.java
@@ -3,6 +3,8 @@
import com.yuanchu.limslaboratory.pojo.User;
import com.baomidou.mybatisplus.extension.service.IService;
+import java.io.Serializable;
+
/**
* <p>
* 鏈嶅姟绫�
@@ -13,4 +15,5 @@
*/
public interface UserService extends IService<User> {
+ User AccordingUsernameSelectAll(String account);
}
diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/service/impl/UserServiceImpl.java b/user-server/src/main/java/com/yuanchu/limslaboratory/service/impl/UserServiceImpl.java
index 6cf6e1f..beb4cea 100644
--- a/user-server/src/main/java/com/yuanchu/limslaboratory/service/impl/UserServiceImpl.java
+++ b/user-server/src/main/java/com/yuanchu/limslaboratory/service/impl/UserServiceImpl.java
@@ -1,10 +1,13 @@
package com.yuanchu.limslaboratory.service.impl;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yuanchu.limslaboratory.pojo.User;
import com.yuanchu.limslaboratory.mapper.UserMapper;
import com.yuanchu.limslaboratory.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
/**
* <p>
@@ -17,4 +20,13 @@
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
+ @Resource
+ private UserMapper mapper;
+
+ @Override
+ public User AccordingUsernameSelectAll(String account) {
+ LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
+ wrapper.eq(User::getAccount, account);
+ return mapper.selectOne(wrapper);
+ }
}
diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/JwtToken.java b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/JwtToken.java
new file mode 100644
index 0000000..e4872db
--- /dev/null
+++ b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/JwtToken.java
@@ -0,0 +1,28 @@
+package com.yuanchu.limslaboratory.shiro;
+
+import com.yuanchu.limslaboratory.shiro.utils.JwtUtils;
+import org.apache.shiro.authc.AuthenticationToken;
+
+public class JwtToken implements AuthenticationToken {
+ private static final long serialVersionUID = 1L;
+
+ // 鍔犲瘑鍚庣殑 JWT token涓�
+ private String token;
+
+ private String account;
+
+ public JwtToken(String token) {
+ this.token = token;
+ this.account = JwtUtils.getClaimFiled(token, "account");
+ }
+
+ @Override
+ public Object getPrincipal() {
+ return this.account;
+ }
+
+ @Override
+ public Object getCredentials() {
+ return token;
+ }
+}
diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/MultiRealmAuthenticator.java b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/MultiRealmAuthenticator.java
new file mode 100644
index 0000000..4110709
--- /dev/null
+++ b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/MultiRealmAuthenticator.java
@@ -0,0 +1,61 @@
+package com.yuanchu.limslaboratory.shiro;
+
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.pam.AuthenticationStrategy;
+import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
+import org.apache.shiro.realm.Realm;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+
+public class MultiRealmAuthenticator extends ModularRealmAuthenticator {
+ private static final Logger log = LoggerFactory.getLogger(MultiRealmAuthenticator.class);
+
+ @Override
+ protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token)
+ throws AuthenticationException {
+ AuthenticationStrategy strategy = getAuthenticationStrategy();
+
+ AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token);
+
+ if (log.isTraceEnabled()) {
+ log.trace("Iterating through {} realms for PAM authentication", realms.size());
+ }
+ AuthenticationException authenticationException = null;
+ for (Realm realm : realms) {
+
+ aggregate = strategy.beforeAttempt(realm, token, aggregate);
+
+ if (realm.supports(token)) {
+
+ log.trace("Attempting to authenticate token [{}] using realm [{}]", token, realm);
+
+ AuthenticationInfo info = null;
+ try {
+ info = realm.getAuthenticationInfo(token);
+ } catch (AuthenticationException e) {
+ authenticationException = e;
+ if (log.isDebugEnabled()) {
+ String msg = "Realm [" + realm
+ + "] threw an exception during a multi-realm authentication attempt:";
+ log.debug(msg, e);
+ }
+ }
+
+ aggregate = strategy.afterAttempt(realm, token, info, aggregate, authenticationException);
+
+ } else {
+ log.debug("Realm [{}] does not support token {}. Skipping realm.", realm, token);
+ }
+ }
+ if (authenticationException != null) {
+ throw authenticationException;
+ }
+ aggregate = strategy.afterAllAttempts(token, aggregate);
+
+ return aggregate;
+ }
+}
diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/config/ShiroConfig.java b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/config/ShiroConfig.java
new file mode 100644
index 0000000..be5d706
--- /dev/null
+++ b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/config/ShiroConfig.java
@@ -0,0 +1,167 @@
+package com.yuanchu.limslaboratory.shiro.config;
+
+import com.yuanchu.limslaboratory.shiro.filter.JwtFilter;
+import com.yuanchu.limslaboratory.shiro.MultiRealmAuthenticator;
+import com.yuanchu.limslaboratory.shiro.realm.JwtRealm;
+import com.yuanchu.limslaboratory.shiro.realm.ShiroRealm;
+import com.yuanchu.limslaboratory.shiro.utils.JwtCredentialsMatcher;
+import org.apache.shiro.authc.credential.CredentialsMatcher;
+import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
+import org.apache.shiro.authc.pam.AuthenticationStrategy;
+import org.apache.shiro.authc.pam.FirstSuccessfulStrategy;
+import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
+import org.apache.shiro.authz.Authorizer;
+import org.apache.shiro.authz.ModularRealmAuthorizer;
+import org.apache.shiro.crypto.hash.Md5Hash;
+import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
+import org.apache.shiro.mgt.DefaultSubjectDAO;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.mgt.SessionStorageEvaluator;
+import org.apache.shiro.realm.Realm;
+import org.apache.shiro.spring.LifecycleBeanPostProcessor;
+import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
+import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
+import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
+import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.servlet.Filter;
+import java.util.*;
+
+@Configuration
+public class ShiroConfig {
+
+ /**
+ * 涓嶅悜 Spring瀹瑰櫒涓敞鍐� JwtFilter Bean锛岄槻姝� Spring 灏� JwtFilter 娉ㄥ唽涓哄叏灞�杩囨护鍣�
+ * 鍏ㄥ眬杩囨护鍣ㄤ細瀵规墍鏈夎姹傝繘琛屾嫤鎴紝鑰屾湰渚嬩腑鍙渶瑕佹嫤鎴櫎 /login 鍜� /logout 澶栫殑璇锋眰
+ * 鍙︿竴绉嶇畝鍗曞仛娉曟槸锛氱洿鎺ュ幓鎺� jwtFilter()涓婄殑 @Bean 娉ㄨВ
+ */
+ @Bean
+ public FilterRegistrationBean<Filter> registration(JwtFilter filter) {
+ FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<Filter>(filter);
+ registration.setEnabled(false);
+ return registration;
+ }
+
+ //ShiroFilter杩囨护鎵�鏈夎姹�
+ @Bean
+ public ShiroFilterFactoryBean getShiroFilterFactoryBean(SecurityManager securityManager) {
+ ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
+ //缁橲hiroFilter閰嶇疆瀹夊叏绠$悊鍣�
+ shiroFilterFactoryBean.setSecurityManager(securityManager);
+
+ // 娣诲姞 jwt 涓撶敤杩囨护鍣紝鎷︽埅闄� /login 鍜� /logout 澶栫殑璇锋眰
+ Map<String, Filter> filterMap = new LinkedHashMap<>();
+ filterMap.put("jwtFilter", new JwtFilter());
+ shiroFilterFactoryBean.setFilters(filterMap);
+
+ //閰嶇疆绯荤粺鍏叡璧勬簮
+ Map<String, String> map = new HashMap<String, String>();
+
+ // swagger鏀捐
+ map.put("/doc.html", "anon");
+ map.put("/webjars/**/**", "anon");
+ map.put("/swagger-resources", "anon");
+ map.put("/api-docs", "anon");
+ map.put("/v3/**", "anon");
+
+
+ map.put("/user/login/**","anon");//琛ㄧず杩欎釜涓哄叕鍏辫祫婧� 涓�瀹氭槸鍦ㄥ彈闄愯祫婧愪笂闈�
+// map.put("/**","jwtFilter");//琛ㄧず杩欎釜璧勬簮闇�瑕佽璇佸拰鎺堟潈
+
+ shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
+
+ return shiroFilterFactoryBean;
+ }
+
+ /**
+ * 閰嶇疆 ModularRealmAuthenticator
+ */
+ @Bean
+ public ModularRealmAuthenticator authenticator() {
+ ModularRealmAuthenticator authenticator = new MultiRealmAuthenticator();
+ // 璁剧疆澶� Realm鐨勮璇佺瓥鐣ワ紝榛樿 AtLeastOneSuccessfulStrategy
+ AuthenticationStrategy strategy = new FirstSuccessfulStrategy();
+ authenticator.setAuthenticationStrategy(strategy);
+ return authenticator;
+ }
+
+
+ /**
+ * 绂佺敤session, 涓嶄繚瀛樼敤鎴风櫥褰曠姸鎬併�備繚璇佹瘡娆¤姹傞兘閲嶆柊璁よ瘉
+ */
+ @Bean
+ protected SessionStorageEvaluator sessionStorageEvaluator() {
+ DefaultSessionStorageEvaluator sessionStorageEvaluator = new DefaultSessionStorageEvaluator();
+ sessionStorageEvaluator.setSessionStorageEnabled(false);
+ return sessionStorageEvaluator;
+ }
+
+ /**
+ * 閰嶇疆 SecurityManager锛氭潈闄愮鐞嗗櫒
+ */
+ @Bean
+ public DefaultWebSecurityManager securityManager() {
+ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
+
+ // 1.韬唤楠岃瘉鍣�
+ securityManager.setAuthenticator(authenticator());
+
+ // 2.绠$悊Realm
+ List<Realm> realms = new ArrayList<Realm>(16);
+ realms.add(JwtRealm());
+ realms.add(shiroRealm());
+ securityManager.setRealms(realms); // 閰嶇疆澶氫釜realm
+
+ // 3.鍏抽棴shiro鑷甫鐨剆ession
+ DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
+ subjectDAO.setSessionStorageEvaluator(sessionStorageEvaluator());
+ securityManager.setSubjectDAO(subjectDAO);
+
+ return securityManager;
+ }
+
+// 鍒涘缓鑷畾涔塕ealm
+ @Bean
+ public Realm shiroRealm() {
+ return new ShiroRealm();
+ }
+
+ @Bean
+ public Realm JwtRealm(){
+ return new JwtRealm();
+ }
+
+
+ // 浠ヤ笅涓変腑bean閫氱敤锛屽浐瀹氶厤缃�
+
+ /**
+ * 浜ょ敱 Spring 鏉ヨ嚜鍔ㄥ湴绠$悊 Shiro-Bean 鐨勭敓鍛藉懆鏈�
+ */
+ @Bean
+ public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
+ return new LifecycleBeanPostProcessor();
+ }
+
+ /**
+ * 涓� Spring-Bean 寮�鍚 Shiro 娉ㄨВ鐨勬敮鎸�
+ */
+ @Bean
+ public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
+ AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
+ authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
+ return authorizationAttributeSourceAdvisor;
+ }
+
+ /**
+ * 寮�鍚疉OP鏂规硶绾ф潈闄愭鏌�
+ */
+ @Bean
+ public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
+ DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
+ advisorAutoProxyCreator.setProxyTargetClass(true);
+ return advisorAutoProxyCreator;
+ }
+}
diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/filter/JwtFilter.java b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/filter/JwtFilter.java
new file mode 100644
index 0000000..a03022e
--- /dev/null
+++ b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/filter/JwtFilter.java
@@ -0,0 +1,170 @@
+package com.yuanchu.limslaboratory.shiro.filter;
+
+import com.yuanchu.limslaboratory.shiro.JwtToken;
+import com.yuanchu.limslaboratory.shiro.utils.JwtUtils;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
+import org.apache.shiro.web.util.WebUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.PrintWriter;
+
+@Component
+public class JwtFilter extends BasicHttpAuthenticationFilter {
+ private Logger log = LoggerFactory.getLogger(this.getClass());
+
+ public Integer code;
+ public String message;
+
+ /**
+ * 鍓嶇疆澶勭悊
+ */
+ @Override
+ protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
+ HttpServletRequest httpServletRequest = WebUtils.toHttp(request);
+ HttpServletResponse httpServletResponse = WebUtils.toHttp(response);
+ // 璺ㄥ煙鏃朵細棣栧厛鍙戦�佷竴涓猳ption璇锋眰锛岃繖閲屾垜浠粰option璇锋眰鐩存帴杩斿洖姝e父鐘舵��
+ if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
+ httpServletResponse.setStatus(HttpStatus.OK.value());
+ return false;
+ }
+ return super.preHandle(request, response);
+ }
+
+ /**
+ * 鍚庣疆澶勭悊
+ */
+ @Override
+ protected void postHandle(ServletRequest request, ServletResponse response) {
+ // 娣诲姞璺ㄥ煙鏀寔
+ this.fillCorsHeader(WebUtils.toHttp(request), WebUtils.toHttp(response));
+ }
+
+ /**
+ * 杩囨护鍣ㄦ嫤鎴姹傜殑鍏ュ彛鏂规硶
+ * 杩斿洖 true 鍒欏厑璁歌闂�
+ * 杩斿洖false 鍒欑姝㈣闂紝浼氳繘鍏� onAccessDenied()
+ */
+ @Override
+ protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
+ // 濡傛灉token涓虹┖涓嶈閫氳繃
+ String header = ((HttpServletRequest) request).getHeader(JwtUtils.AUTH_HEADER);
+ if (ObjectUtils.isEmpty(header)){
+ code = 503;
+ message = "STS token瑙g爜杩囩▼涓紝鐢变簬鍐呴儴璋冪敤澶辫触瀵艰嚧瑙g爜澶辫触锛岃绋嶅悗鍐嶈瘯銆�";
+ return false;
+ }
+ boolean allowed = false;
+ try {
+ // 妫�娴婬eader閲岀殑 JWT token鍐呭鏄惁姝g‘锛屽皾璇曚娇鐢� token杩涜鐧诲綍
+ allowed = executeLogin(request, response);
+ } catch (IllegalStateException e) { // not found any token
+ log.error("Not found any token");
+ } catch (Exception e) {
+ log.error("Error occurs when login", e);
+ }
+ return allowed || super.isPermissive(mappedValue);
+ }
+
+
+ /**
+ * 韬唤楠岃瘉,妫�鏌� JWT token 鏄惁鍚堟硶
+ */
+ @Override
+ protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
+ AuthenticationToken token = createToken(request, response);
+ if (token == null) {
+ String msg = "createToken method implementation returned null. A valid non-null AuthenticationToken "
+ + "must be created in order to execute a login attempt.";
+ throw new IllegalStateException(msg);
+ }
+
+ try {
+ Subject subject = getSubject(request, response);
+ subject.login(token); // 浜ょ粰 Shiro 鍘昏繘琛岀櫥褰曢獙璇�
+ return onLoginSuccess(token, subject, request, response);
+ } catch (AuthenticationException e) {
+ return onLoginFailure(token, e, request, response);
+ }
+ }
+
+ /**
+ * 浠� Header 閲屾彁鍙� JWT token
+ */
+ @Override
+ protected AuthenticationToken createToken(ServletRequest servletRequest, ServletResponse servletResponse) {
+ HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
+ String authorization = httpServletRequest.getHeader(JwtUtils.AUTH_HEADER);
+ JwtToken token = new JwtToken(authorization);
+ return token;
+ }
+
+ /**
+ * isAccessAllowed()鏂规硶杩斿洖false锛屼細杩涘叆璇ユ柟娉曪紝琛ㄧず鎷掔粷璁块棶
+ */
+ @Override
+ protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
+ HttpServletResponse httpResponse = WebUtils.toHttp(servletResponse);
+ httpResponse.setCharacterEncoding("UTF-8");
+ httpResponse.setContentType("application/json;charset=UTF-8");
+ httpResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
+ PrintWriter writer = httpResponse.getWriter();
+ writer.write("{\"errCode\": "+ code +", \"msg\": \"" + message +"\"}");
+ fillCorsHeader(WebUtils.toHttp(servletRequest), httpResponse);
+ return false;
+ }
+
+ /**
+ * Shiro 鍒╃敤 JWT token 鐧诲綍鎴愬姛锛屼細杩涘叆璇ユ柟娉�
+ */
+ @Override
+ protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,
+ ServletResponse response) {
+ HttpServletResponse httpResponse = WebUtils.toHttp(response);
+ String newToken = null;
+ if (token instanceof JwtToken) {
+ newToken = JwtUtils.refreshTokenExpired(token.getCredentials().toString(), JwtUtils.SECRET);
+ }
+ if (newToken != null)
+ httpResponse.setHeader(JwtUtils.AUTH_HEADER, newToken);
+ return true;
+ }
+
+ /**
+ * Shiro 鍒╃敤 JWT token 鐧诲綍澶辫触锛屼細杩涘叆璇ユ柟娉�
+ */
+ @Override
+ protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request,
+ ServletResponse response) {
+ // 姝ゅ鐩存帴杩斿洖 false 锛屼氦缁欏悗闈㈢殑 onAccessDenied()鏂规硶杩涜澶勭悊
+ String error = e.getClass().toString().split("\\.")[4];
+ if (error.equals("IncorrectCredentialsException")) {
+ code = 10010;
+ } else {
+ code = 401;
+ }
+ message = e.getMessage();
+ return false;
+ }
+
+ /**
+ * 娣诲姞璺ㄥ煙鏀寔
+ */
+ protected void fillCorsHeader(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
+ httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));
+ httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,HEAD");
+ httpServletResponse.setHeader("Access-Control-Allow-Headers",
+ httpServletRequest.getHeader("Access-Control-Request-Headers"));
+ }
+}
diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/realm/JwtRealm.java b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/realm/JwtRealm.java
new file mode 100644
index 0000000..4293742
--- /dev/null
+++ b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/realm/JwtRealm.java
@@ -0,0 +1,57 @@
+package com.yuanchu.limslaboratory.shiro.realm;
+
+import com.yuanchu.limslaboratory.pojo.User;
+import com.yuanchu.limslaboratory.shiro.JwtToken;
+import com.yuanchu.limslaboratory.shiro.utils.JwtCredentialsMatcher;
+import com.yuanchu.limslaboratory.utils.RedisUtil;
+import org.apache.shiro.authc.*;
+import org.apache.shiro.authc.credential.CredentialsMatcher;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.authz.SimpleAuthorizationInfo;
+import org.apache.shiro.realm.AuthorizingRealm;
+import org.apache.shiro.subject.PrincipalCollection;
+
+public class JwtRealm extends AuthorizingRealm {
+ /**
+ * 闄愬畾杩欎釜 Realm 鍙鐞嗘垜浠嚜瀹氫箟鐨� JwtToken
+ */
+ @Override
+ public boolean supports(AuthenticationToken token) {
+ return token instanceof JwtToken;
+ }
+
+ /**
+ * 姝ゅ鐨� SimpleAuthenticationInfo 鍙繑鍥炰换鎰忓�硷紝瀵嗙爜鏍¢獙鏃朵笉浼氱敤鍒板畠
+ */
+ @Override
+ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
+ JwtToken jwtToken = (JwtToken) authcToken;
+ if (jwtToken.getPrincipal() == null) {
+ throw new AccountException("Token鍙傛暟寮傚父锛�");
+ }
+ // 褰撳墠鐢ㄦ埛
+ String account = jwtToken.getPrincipal().toString();
+ // 褰撳墠鐢ㄦ埛鐨則oken
+ String credentials = (String)jwtToken.getCredentials();
+ User user = (User) RedisUtil.get(credentials);
+ // 鐢ㄦ埛涓嶅瓨鍦�
+ if (user == null) {
+ throw new UnknownAccountException("鐢ㄦ埛涓嶅瓨鍦紒");
+ }
+ SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, account, getName());
+ return info;
+ }
+
+ @Override
+ protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
+ SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
+ return info;
+ }
+
+ @Override
+ public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
+ // 璁剧疆鍔犲瘑绠楁硶
+ CredentialsMatcher jwtCredentialsMatcher = new JwtCredentialsMatcher();
+ super.setCredentialsMatcher(jwtCredentialsMatcher);
+ }
+}
diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/realm/ShiroRealm.java b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/realm/ShiroRealm.java
new file mode 100644
index 0000000..ec429f4
--- /dev/null
+++ b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/realm/ShiroRealm.java
@@ -0,0 +1,55 @@
+package com.yuanchu.limslaboratory.shiro.realm;
+
+import com.yuanchu.limslaboratory.pojo.User;
+import com.yuanchu.limslaboratory.service.UserService;
+import com.yuanchu.limslaboratory.utils.MyUtils;
+import com.yuanchu.limslaboratory.utils.SpringUtils;
+import org.apache.shiro.authc.*;
+import org.apache.shiro.authc.credential.CredentialsMatcher;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.realm.AuthorizingRealm;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.springframework.util.ObjectUtils;
+
+public class ShiroRealm extends AuthorizingRealm {
+
+ public User user;
+
+ /**
+ * 闄愬畾杩欎釜 Realm 鍙鐞� UsernamePasswordToken
+ */
+ @Override
+ public boolean supports(AuthenticationToken token) {
+ return token instanceof UsernamePasswordToken;
+ }
+
+ @Override
+ protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
+ return null;
+ }
+
+ @Override
+ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {
+ String principal = (String) authenticationToken.getPrincipal();
+ //鑾峰彇UserService瀵硅薄
+ UserService userService = SpringUtils.getBean(UserService.class);
+ user = userService.AccordingUsernameSelectAll(principal);
+ MyUtils.PrintLog(user.toString());
+ if (!ObjectUtils.isEmpty(user)) {
+ return new SimpleAuthenticationInfo(user.getAccount(), user.getPassword(), this.getName());
+ } else {
+ throw new UnknownAccountException();
+ }
+ }
+
+ @Override
+ public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
+// HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
+// //璁剧疆浣跨敤MD5鍔犲瘑绠楁硶
+// hashedCredentialsMatcher.setHashAlgorithmName(Md5Hash.ALGORITHM_NAME);
+// //鏁e垪娆℃暟
+// hashedCredentialsMatcher.setHashIterations(1024);
+// super.setCredentialsMatcher(hashedCredentialsMatcher);
+ super.setCredentialsMatcher(credentialsMatcher);
+ }
+}
diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/utils/JwtCredentialsMatcher.java b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/utils/JwtCredentialsMatcher.java
new file mode 100644
index 0000000..a04c5b6
--- /dev/null
+++ b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/utils/JwtCredentialsMatcher.java
@@ -0,0 +1,34 @@
+package com.yuanchu.limslaboratory.shiro.utils;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.JWTVerifier;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.exceptions.JWTVerificationException;
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.credential.CredentialsMatcher;
+import org.springframework.stereotype.Component;
+
+@Component
+public class JwtCredentialsMatcher implements CredentialsMatcher {
+ /**
+ * JwtCredentialsMatcher鍙渶楠岃瘉JwtToken鍐呭鏄惁鍚堟硶
+ */
+ @Override
+ public boolean doCredentialsMatch(AuthenticationToken authenticationToken, AuthenticationInfo authenticationInfo) {
+
+ String token = authenticationToken.getCredentials().toString();
+ String account = authenticationToken.getPrincipal().toString();
+ try {
+ Algorithm algorithm = Algorithm.HMAC256(JwtUtils.getSecret());
+ JWTVerifier verifier = JWT.require(algorithm).withClaim("account", account).build();
+ verifier.verify(token);
+ return true;
+ } catch (JWTVerificationException e) {
+
+ } catch (Exception e){
+ e.printStackTrace();
+ }
+ return false;
+ }
+}
diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/utils/JwtUtils.java b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/utils/JwtUtils.java
new file mode 100644
index 0000000..f2cd618
--- /dev/null
+++ b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/utils/JwtUtils.java
@@ -0,0 +1,160 @@
+package com.yuanchu.limslaboratory.shiro.utils;
+
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.JWTCreator;
+import com.auth0.jwt.JWTVerifier;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.exceptions.JWTCreationException;
+import com.auth0.jwt.exceptions.JWTDecodeException;
+import com.auth0.jwt.exceptions.JWTVerificationException;
+import com.auth0.jwt.interfaces.Claim;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
+
+import javax.annotation.PostConstruct;
+import java.io.UnsupportedEncodingException;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Map;
+
+@Component
+public class JwtUtils {
+ private static String staticSecret;
+
+ @Value("${login.secret}")
+ private String secret;
+
+ @PostConstruct
+ public void getApiToken() {
+ staticSecret = this.secret;
+ }
+
+ public static String getSecret() {
+ // lockie.zou
+ return staticSecret;
+ }
+
+ // 杩囨湡鏃堕棿 2 灏忔椂
+ private static final long EXPIRE_TIME = 2 * 60 * 60 * 1000;
+ //鑷繁瀹氬埗瀵嗛挜
+ public static final String SECRET = "J-(t]Poe9P";
+
+ //璇锋眰澶�
+ public static final String AUTH_HEADER = "X-Token"; // X-Authorization-With
+
+ /**
+ * 楠岃瘉token鏄惁姝g‘
+ * @param token
+ * @return
+ */
+ public static boolean verify(String token){
+ try{
+ String account = getClaimFiled(token, "account");
+ if (account == null){
+ return false;
+ }
+ Algorithm algorithm = Algorithm.HMAC256(getSecret());
+ JWTVerifier verifier = JWT.require(algorithm).withClaim("account",account).build();
+ verifier.verify(token);
+ return true;
+ } catch (JWTVerificationException exception){
+ return false;
+ } catch (Exception e){
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ /**
+ * 鑾峰緱token涓殑鑷畾涔変俊鎭�,涓�鑸槸鑾峰彇token鐨剈sername锛屾棤闇�secret瑙e瘑涔熻兘鑾峰緱
+ * @param token
+ * @param filed
+ * @return
+ */
+ public static String getClaimFiled(String token, String filed){
+ try{
+ if (!ObjectUtils.isEmpty(token)){
+ DecodedJWT jwt = JWT.decode(token);
+ return jwt.getClaim(filed).asString();
+ }
+ return null;
+ } catch (JWTDecodeException e){
+ return null;
+ }
+ }
+
+ /**
+ * 鐢熸垚绛惧悕,鍑嗙‘鍦拌鏄敓鎴恡oken
+ * @return
+ */
+ public static String sign(String account){
+ try{
+ Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
+ Algorithm algorithm = Algorithm.HMAC256(SECRET);
+ //闄勫甫username,nickname淇℃伅
+ return JWT.create()
+ .withClaim("account",account)
+ .withExpiresAt(date)
+ .sign(algorithm);
+ } catch (JWTCreationException e){
+ e.printStackTrace();
+ return null;
+ } catch (Exception e){
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * 鑾峰彇token鐨勭鍙戞椂闂�
+ * @param token
+ * @return
+ */
+ public static Date getIssueAt(String token){
+ try{
+ DecodedJWT jwt = JWT.decode(token);
+ return jwt.getIssuedAt();
+ } catch (JWTDecodeException e){
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * 楠岃瘉token鏄惁杩囨湡
+ * @param token
+ * @return
+ */
+ public static boolean isTokenExpired(String token){
+ Date now = Calendar.getInstance().getTime();
+ DecodedJWT jwt = JWT.decode(token);
+ return jwt.getExpiresAt().before(now);
+ }
+
+ /**
+ * 鍒锋柊token鐨勬湁鏁堟湡
+ * @param token
+ * @param secret
+ * @return
+ */
+ public static String refreshTokenExpired(String token, String secret){
+ DecodedJWT jwt = JWT.decode(token); //瑙f瀽token
+ Map<String, Claim> claims = jwt.getClaims(); //鑾峰彇token鐨勫弬鏁颁俊鎭�
+
+ try{
+ Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
+ Algorithm algorithm = Algorithm.HMAC256(secret);
+ JWTCreator.Builder builder = JWT.create().withExpiresAt(date);
+ for(Map.Entry<String,Claim> entry : claims.entrySet()){
+ builder.withClaim(entry.getKey(),entry.getValue().asString());
+ }
+ return builder.sign(algorithm);
+ } catch (JWTCreationException e){
+ e.printStackTrace();
+ return null;
+ }
+ }
+}
diff --git a/user-server/src/main/resources/mapper/AdminMapper.xml b/user-server/src/main/resources/mapper/AdminMapper.xml
deleted file mode 100644
index cfa44cb..0000000
--- a/user-server/src/main/resources/mapper/AdminMapper.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.yuanchu.limslaboratory.mapper.AdminMapper">
-
-</mapper>
--
Gitblit v1.9.3