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