From d5bdf4cd56be6bd0e7afa81d75c35a9f15ae2a40 Mon Sep 17 00:00:00 2001
From: jiangping <jp@doumee.com>
Date: 星期四, 21 九月 2023 09:09:32 +0800
Subject: [PATCH] 主播接口

---
 server/zhubo/src/main/java/com/doumee/config/shiro/ShiroCacheManager.java               |   44 +
 server/zhubo/src/main/java/com/doumee/config/shiro/ShiroConfig.java                     |  153 ++++
 server/zhubo/src/main/java/com/doumee/config/swagger/SwaggerInterceptorConfig.java      |   22 
 server/service/src/main/java/com/doumee/service/business/impl/BaseGoodsServiceImpl.java |    3 
 server/zhubo/src/main/java/com/doumee/api/business/CategoryController.java              |  106 +++
 .idea/encodings.xml                                                                     |    2 
 server/zhubo/src/main/java/com/doumee/api/business/GoodsController.java                 |   71 ++
 server/company/src/main/java/com/doumee/config/shiro/ShiroConfig.java                   |    2 
 server/zhubo/src/main/java/com/doumee/config/shiro/ShiroSessionSerializer.java          |   36 +
 server/zhubo/src/main/java/com/doumee/api/business/WebParamController.java              |   48 +
 .idea/misc.xml                                                                          |    1 
 server/zhubo/src/main/java/com/doumee/Main.java                                         |    7 
 server/zhubo/src/main/java/com/doumee/api/business/BrandController.java                 |   41 +
 server/zhubo/src/main/java/com/doumee/config/shiro/ShiroToken.java                      |   54 +
 server/zhubo/src/main/java/com/doumee/config/shiro/ShiroCredentialsMatcher.java         |   46 +
 server/zhubo/src/main/resources/application.yml                                         |   64 ++
 server/zhubo/src/main/java/com/doumee/api/business/CateBudgetController.java            |   36 +
 server/zhubo/pom.xml                                                                    |   61 +
 server/zhubo/src/main/java/com/doumee/config/shiro/ShiroRealm.java                      |  115 +++
 server/zhubo/src/main/java/com/doumee/config/swagger/SwaggerInterceptor.java            |   45 +
 server/company/src/main/java/com/doumee/config/shiro/ShiroAuthFilter.java               |  111 ---
 server/service/src/main/java/com/doumee/service/business/impl/BaseDataServiceImpl.java  |    3 
 server/zhubo/src/main/java/com/doumee/api/BaseController.java                           |   60 +
 server/zhubo/src/main/java/com/doumee/config/shiro/ShiroCache.java                      |  163 +++++
 server/zhubo/src/main/java/com/doumee/config/shiro/ShiroAuthFilter2.java                |    0 
 server/zhubo/src/main/java/com/doumee/api/system/SystemController.java                  |   66 ++
 server/zhubo/src/main/java/com/doumee/config/shiro/ShiroTokenManager.java               |   25 
 server/company/src/main/resources/application.yml                                       |    2 
 server/service/src/main/java/com/doumee/service/business/impl/GoodsServiceImpl.java     |   18 
 server/zhubo/src/main/java/com/doumee/config/shiro/ShiroAuthFilter.java                 |  144 ++++
 server/pom.xml                                                                          |    1 
 server/zhubo/src/main/java/com/doumee/config/shiro/ShiroSessionManager.java             |   85 ++
 .idea/compiler.xml                                                                      |    7 
 server/zhubo/src/main/java/com/doumee/ZhuboApplication.java                             |   25 
 server/zhubo/src/main/java/com/doumee/config/shiro/ShiroSessionDAO.java                 |  113 +++
 server/zhubo/src/main/java/com/doumee/config/swagger/SwaggerConfig.java                 |   88 ++
 server/company/src/main/java/com/doumee/config/shiro/ShiroRealm.java                    |    2 
 37 files changed, 1,752 insertions(+), 118 deletions(-)

diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 92917a1..bca72a5 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -6,22 +6,27 @@
         <sourceOutputDir name="target/generated-sources/annotations" />
         <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
         <outputRelativeToContentRoot value="true" />
+        <module name="company" />
+        <module name="zhubo" />
         <module name="platform" />
         <module name="service" />
-        <module name="company" />
       </profile>
     </annotationProcessing>
     <bytecodeTargetLevel>
+      <module name="company (1)" target="1.8" />
+      <module name="company (2)" target="1.8" />
       <module name="pre_select" target="1.8" />
     </bytecodeTargetLevel>
   </component>
   <component name="JavacSettings">
     <option name="ADDITIONAL_OPTIONS_OVERRIDE">
       <module name="company" options="-parameters" />
+      <module name="company (1)" options="-parameters" />
       <module name="platform" options="-parameters" />
       <module name="pre_select" options="" />
       <module name="preselect" options="-parameters" />
       <module name="service" options="-parameters" />
+      <module name="zhubo" options="-parameters" />
     </option>
   </component>
 </project>
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
index 0956fda..0ce3556 100644
--- a/.idea/encodings.xml
+++ b/.idea/encodings.xml
@@ -9,5 +9,7 @@
     <file url="file://$PROJECT_DIR$/server/service/src/main/resources" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/server/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/server/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/server/zhubo/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/server/zhubo/src/main/resources" charset="UTF-8" />
   </component>
 </project>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 66c9c8c..a676599 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -5,6 +5,7 @@
     <option name="originalFiles">
       <list>
         <option value="$PROJECT_DIR$/server/pom.xml" />
+        <option value="$PROJECT_DIR$/server/zhubo/pom.xml" />
       </list>
     </option>
   </component>
diff --git a/server/company/src/main/java/com/doumee/config/shiro/ShiroAuthFilter.java b/server/company/src/main/java/com/doumee/config/shiro/ShiroAuthFilter.java
index 28b01dc..853e2bb 100644
--- a/server/company/src/main/java/com/doumee/config/shiro/ShiroAuthFilter.java
+++ b/server/company/src/main/java/com/doumee/config/shiro/ShiroAuthFilter.java
@@ -27,119 +27,12 @@
  */
 public class ShiroAuthFilter extends FormAuthenticationFilter {
 
-    public ShiroAuthFilter(SessionManager sessionManager,ShiroCacheManager shiroCacheManager) {
-        super();
-        this.sessionManager =   (ShiroSessionManager)sessionManager;
-        this.cache = shiroCacheManager.getCache("shiro_redis_cache");
-    }
-    @Override
-    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)  {
-        return false;
-    }
+        @Override
+        protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
 
-    private int maxSession = 1; //鏈�澶т細璇濇暟閲�
-
-    private boolean kickOutAfter = false;   //韪㈠嚭鍓嶈�呰繕鏄悗鑰�
-    private Cache<String, Deque<Serializable>> cache; //缂撳瓨绠$悊
-
-
-    private ShiroSessionManager sessionManager;  //浼氳瘽绠$悊
-
-    @Override
-    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
-        Subject subject = getSubject(request, response);
-        if (!subject.isAuthenticated() && !subject.isRemembered()) { //濡傛灉涓嶆槸璁よ瘉杩囧拰璁颁綇瀵嗙爜鐨勶紝灏辩洿鎺ユ斁琛岃姹傦紝閬垮厤閫犳垚璁块棶杩囨參
-           // return Boolean.TRUE;
-        }
-        Session session = subject.getSession(); //鑾峰彇浼氳瘽session
-        Object principal = subject.getPrincipal();
-        Serializable sessionId = session.getId();
-        LoginUserInfo userInfo = (LoginUserInfo) principal;
-        if(userInfo == null  ){
-            HttpServletResponse servletResponse = (HttpServletResponse) response;
-            servletResponse.setHeader("content-type", "application/json;charset=UTF-8");
-            servletResponse.getWriter().write(JSON.toJSONString(ApiResponse.failed(HttpStatus.UNAUTHORIZED.value(), "鏈櫥褰曟垨鐧诲綍淇℃伅宸茶繃鏈�")));
-            return Boolean.FALSE;
-//           return  super.onAccessDenied(request,response);
-        }else if( Constants.equalsInteger(userInfo.getType(), Constants.UserType.COMPANY.getKey()) ){
-            return Boolean.TRUE;
-//           return  super.onAccessDenied(request,response);
-        }
-
-        String userName = userInfo.getCompanyId() +"_"+ userInfo.getId();
-        Deque<Serializable> deque = cache.get(userName);
-        if (deque == null) {
-            deque = new LinkedList<>();
-        }
-        if (!deque.contains(sessionId) && session.getAttribute("kickOut") == null) {
-            deque.push(sessionId);
-            cache.put(userName, deque);
-        }
-        while (deque.size() > maxSession) {
-            Serializable kickOutSessionId;
-            if (kickOutAfter) {
-                kickOutSessionId = deque.removeFirst();
-                cache.put(userName, deque);
-            } else {
-                kickOutSessionId = deque.removeLast();
-                cache.put(userName, deque);
-            }
-
-            try {
-                Session kickOutSession = sessionManager.getSession(new DefaultSessionKey(kickOutSessionId));
-                if (kickOutSession != null) {
-                    kickOutSession.setAttribute("kickOut", Boolean.TRUE);
-                }
-            } catch (Exception e) {
-                e.printStackTrace();
-//                log.error("韪㈠嚭寮傚父鏈涪鍑�");
-            }
-        }
-
-        if (session!=null && session.getAttribute("kickOut") != null && (Boolean) session.getAttribute("kickOut") == true) {
-            try {
-                subject.logout();
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-            saveRequest(request);
             HttpServletResponse servletResponse = (HttpServletResponse) response;
             servletResponse.setHeader("content-type", "application/json;charset=UTF-8");
             servletResponse.getWriter().write(JSON.toJSONString(ApiResponse.failed(HttpStatus.UNAUTHORIZED.value(), "鏈櫥褰曟垨鐧诲綍淇℃伅宸茶繃鏈�")));
             return Boolean.FALSE;
         }
-        return Boolean.TRUE;
-    }
-
-    public int getMaxSession() {
-        return maxSession;
-    }
-
-    public void setMaxSession(int maxSession) {
-        this.maxSession = maxSession;
-    }
-
-    public boolean isKickOutAfter() {
-        return kickOutAfter;
-    }
-
-    public void setKickOutAfter(boolean kickOutAfter) {
-        this.kickOutAfter = kickOutAfter;
-    }
-
-    public Cache<String, Deque<Serializable>> getCache() {
-        return cache;
-    }
-
-    public void setCache(Cache<String, Deque<Serializable>> cache) {
-        this.cache = cache;
-    }
-
-    public ShiroSessionManager getSessionManager() {
-        return sessionManager;
-    }
-
-    public void setSessionManager(ShiroSessionManager sessionManager) {
-        this.sessionManager = sessionManager;
-    }
 }
diff --git a/server/company/src/main/java/com/doumee/config/shiro/ShiroConfig.java b/server/company/src/main/java/com/doumee/config/shiro/ShiroConfig.java
index d9636c8..fdd05c9 100644
--- a/server/company/src/main/java/com/doumee/config/shiro/ShiroConfig.java
+++ b/server/company/src/main/java/com/doumee/config/shiro/ShiroConfig.java
@@ -127,7 +127,7 @@
         shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
         // 娣诲姞璁よ瘉杩囨护鍣�
         Map<String, Filter> filters = new LinkedHashMap<>();
-        filters.put("authc", new ShiroAuthFilter(this.sessionManager(),shiroCacheManager));
+        filters.put("authc", new ShiroAuthFilter());
         shiroFilterFactoryBean.setFilters(filters);
         return shiroFilterFactoryBean;
     }
diff --git a/server/company/src/main/java/com/doumee/config/shiro/ShiroRealm.java b/server/company/src/main/java/com/doumee/config/shiro/ShiroRealm.java
index 1f3e049..14dfc00 100644
--- a/server/company/src/main/java/com/doumee/config/shiro/ShiroRealm.java
+++ b/server/company/src/main/java/com/doumee/config/shiro/ShiroRealm.java
@@ -88,7 +88,7 @@
         if(user == null){
             throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"瀵逛笉璧凤紝璐﹀彿鎴栧瘑鐮佷笉姝g‘锛�");
         }
-        if(!Constants.equalsInteger(user.getType(),Constants.UserType.COMPANY.getKey()) && !Constants.equalsInteger(user.getType(),Constants.UserType.ZHUBO.getKey())){
+        if(!Constants.equalsInteger(user.getType(),Constants.UserType.COMPANY.getKey())){
             throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"瀵逛笉璧凤紝闈炰紒涓氳处鎴疯韩浠斤紝鏃犳硶鐧诲綍璇ュ钩鍙帮紒锛�");
         }
         if(!Constants.equalsInteger(user.getStatus(),Constants.ZERO)){
diff --git a/server/company/src/main/resources/application.yml b/server/company/src/main/resources/application.yml
index 6787c56..ac52ad2 100644
--- a/server/company/src/main/resources/application.yml
+++ b/server/company/src/main/resources/application.yml
@@ -11,7 +11,7 @@
 #  application:
 #    name: doumeemes
   profiles:
-    active: dev
+    active: pro
 
   # JSON杩斿洖閰嶇疆
   jackson:
diff --git a/server/pom.xml b/server/pom.xml
index be687ef..ab0428b 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -13,6 +13,7 @@
     <module>platform</module>
     <module>service</module>
     <module>company</module>
+    <module>zhubo</module>
   </modules>
 
   <parent>
diff --git a/server/service/src/main/java/com/doumee/service/business/impl/BaseDataServiceImpl.java b/server/service/src/main/java/com/doumee/service/business/impl/BaseDataServiceImpl.java
index 03c580a..118f433 100644
--- a/server/service/src/main/java/com/doumee/service/business/impl/BaseDataServiceImpl.java
+++ b/server/service/src/main/java/com/doumee/service/business/impl/BaseDataServiceImpl.java
@@ -384,7 +384,8 @@
                 }
 //                goods.setImgurl(getOssImgurl(ossModel,ossModel.getGoodsFolder(), data.getImgurl()));
                 goods.setImgurl(getOssImgurlFile(ossModel.getGoodsFolder(), data.getImgurl(), data.getId(),Constants.ZERO,fileRecords));
-                goods.setPrice(Constants.formatBigdecimal(data.getSaleprice()).multiply(Constants.formatBigdecimal(cModel.getPriceRate())));
+//                goods.setPrice(Constants.formatBigdecimal(data.getSaleprice()).multiply(Constants.formatBigdecimal(cModel.getPriceRate())));
+                goods.setPrice(Constants.formatBigdecimal(data.getSaleprice()));
                 if(model!=null){
                     //濡傛灉宸茬粡瀛樺湪锛屾洿鏂板晢鍝佹暟鎹�
                     goods.setEditDate(date);
diff --git a/server/service/src/main/java/com/doumee/service/business/impl/BaseGoodsServiceImpl.java b/server/service/src/main/java/com/doumee/service/business/impl/BaseGoodsServiceImpl.java
index ab87999..7c30b43 100644
--- a/server/service/src/main/java/com/doumee/service/business/impl/BaseGoodsServiceImpl.java
+++ b/server/service/src/main/java/com/doumee/service/business/impl/BaseGoodsServiceImpl.java
@@ -391,6 +391,7 @@
                 .leftJoin(BaseCategory.class,BaseCategory::getId,BaseGoods::getCategoryId)
                 .selectAll(BaseGoods.class)
                 .selectAs(Brand::getName,BaseGoods::getBrandName)
+                .selectAs(BaseCategory::getPriceRate,BaseGoods::getCateRatePrice)
                 .selectAs(BaseCategory::getName,BaseGoods::getCategoryName)
                 .eq(BaseGoods::getStatus, Constants.ZERO)
                 .eq(BaseGoods::getIsdeleted, Constants.ZERO)
@@ -406,6 +407,8 @@
                 + systemDictDataBiz.queryByCode(Constants.OSS, Constants.GOODS_IMG).getCode();
         pageData.getRecords().forEach(i->{
             i.setFullImgUrl(prefixUrl + i.getImgurl());
+            //鍔犱环绯绘暟
+            i.setPrice(Constants.formatBigdecimal(i.getPrice()).multiply(Constants.formatBigdecimal(i.getCateRatePrice())));
         });
         return pageData;
     }
diff --git a/server/service/src/main/java/com/doumee/service/business/impl/GoodsServiceImpl.java b/server/service/src/main/java/com/doumee/service/business/impl/GoodsServiceImpl.java
index 553ced0..02cde3d 100644
--- a/server/service/src/main/java/com/doumee/service/business/impl/GoodsServiceImpl.java
+++ b/server/service/src/main/java/com/doumee/service/business/impl/GoodsServiceImpl.java
@@ -66,6 +66,8 @@
     @Autowired
     private CategoryMapper categoryMapper;
     @Autowired
+    private BaseCategoryMapper baseCategoryMapper;
+    @Autowired
     private CateAttrMapper cateAttrMapper;
     @Autowired
     private CateParamMapper cateParamMapper;
@@ -158,6 +160,11 @@
         if(category.getPlatCateId() == null){
             throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"瀵逛笉璧凤紝璇峰墠寰�銆愮被鍒鐞嗐�戝厛鍏宠仈骞冲彴绫诲埆锛�");
         }
+        BaseCategory baseCategory = baseCategoryMapper.selectById(category.getPlatCateId());
+        if(baseCategory == null){
+            throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"瀵逛笉璧凤紝璇峰墠寰�銆愮被鍒鐞嗐�戝厛鍏宠仈骞冲彴绫诲埆锛�");
+        }
+
         BaseGoods bp = new BaseGoods();
         bp.setCategoryId(category.getPlatCateId());
         bp.setIsdeleted(Constants.ZERO);
@@ -185,6 +192,9 @@
         try{
             for(BaseGoods model : goodsList){
                 //閬嶅巻骞冲彴鍟嗗搧淇℃伅锛岃繘琛屽晢鍝佷俊鎭悓姝�
+                //鍒嗙被鍔犱环绯绘暟
+
+                model.setCateRatePrice(baseCategory.getPriceRate());
                 Goods goods = initGoodsPlatParam(user,model,param);
                 if(goods == null){
                     continue;
@@ -310,11 +320,11 @@
             throw new BusinessException(ResponseStatus.DATA_ERRO.getCode(),"鏁版嵁寮傚父璇峰埛鏂伴噸璇�");
         }
         //濡傛灉娌℃湁閰嶇疆鍏ユ墜浠凤紝瀹夎鍔犱环绯绘暟鏉ヨ绠�
-//        if(model.getCateRatePrice()==null){
-//            model.setCateRatePrice(systemDictDataBiz.getGoodsPriceRate());
-//        }
+        if(model.getCateRatePrice()==null){
+            model.setCateRatePrice(systemDictDataBiz.getGoodsPriceRate());
+        }
         //杩斿洖 .multiply(model.getCateRatePrice())
-        return (Constants.formatBigdecimal(model.getPrice()).multiply(param.getRate())).setScale(0,BigDecimal.ROUND_CEILING);
+        return (Constants.formatBigdecimal(model.getPrice()).multiply(model.getCateRatePrice()).multiply(param.getRate())).setScale(0,BigDecimal.ROUND_CEILING);
 
     }
 
diff --git a/server/zhubo/pom.xml b/server/zhubo/pom.xml
new file mode 100644
index 0000000..7645a85
--- /dev/null
+++ b/server/zhubo/pom.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.doumee</groupId>
+        <artifactId>preselect</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>zhubo</artifactId>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.doumee</groupId>
+            <artifactId>service</artifactId>
+            <version>1.0.0-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>company</finalName>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+            </resource>
+        </resources>
+
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <fork>true</fork>
+                    <mainClass>com.doumee.ZhuboApplication</mainClass>
+                    <layout>ZIP</layout>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <!--<plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-war-plugin</artifactId>
+            <version>2.6</version>
+            </plugin>-->
+
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/server/zhubo/src/main/java/com/doumee/Main.java b/server/zhubo/src/main/java/com/doumee/Main.java
new file mode 100644
index 0000000..ada0d0d
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/Main.java
@@ -0,0 +1,7 @@
+package com.doumee;
+
+public class Main {
+    public static void main(String[] args) {
+        System.out.println("Hello world!");
+    }
+}
\ No newline at end of file
diff --git a/server/zhubo/src/main/java/com/doumee/ZhuboApplication.java b/server/zhubo/src/main/java/com/doumee/ZhuboApplication.java
new file mode 100644
index 0000000..845163c
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/ZhuboApplication.java
@@ -0,0 +1,25 @@
+package com.doumee;
+
+import lombok.extern.slf4j.Slf4j;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.context.ApplicationContext;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+/**
+ * 鍚姩绫�
+ * @author Eva.Caesar Liu
+ * @date 2023/02/14 11:14
+ */
+@Slf4j
+@SpringBootApplication
+@MapperScan("com.doumee.dao")
+@EnableAsync
+public class ZhuboApplication {
+    public static void main(String[] args) {
+        ApplicationContext context = SpringApplication.run(ZhuboApplication.class);
+        context.getEnvironment();
+    }
+}
diff --git a/server/zhubo/src/main/java/com/doumee/api/BaseController.java b/server/zhubo/src/main/java/com/doumee/api/BaseController.java
new file mode 100644
index 0000000..c45000d
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/api/BaseController.java
@@ -0,0 +1,60 @@
+package com.doumee.api;
+
+import com.doumee.core.model.LoginUserInfo;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.SecurityUtils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Controller鍩虹被
+ * @author Eva.Caesar Liu
+ * @date 2023/02/14 11:14
+ */
+@Slf4j
+public class BaseController {
+
+    /**
+     * 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛
+     * @author Eva.Caesar Liu
+     * @date 2023/02/14 11:14
+     */
+    protected LoginUserInfo getLoginUser () {
+        return (LoginUserInfo)SecurityUtils.getSubject().getPrincipal();
+    }
+
+    /**
+     * 鑾峰彇ID闆嗗悎
+     *
+     * @param ids 浣跨敤","闅斿紑鐨勫涓狪D
+     * @return List<Integer>
+     */
+    protected List<Integer> getIdList (String ids) {
+        String [] idArray = ids.split(",");
+        List<Integer> idList = new ArrayList<>();
+        for (String id : idArray) {
+            idList.add(Integer.valueOf(id));
+        }
+        return idList;
+    }
+
+    /**
+     * 鑾峰彇鏂囦欢瀛楄妭娴�
+     *
+     * @param is 杈撳叆娴�
+     * @return ByteArrayOutputStream
+     */
+    protected ByteArrayOutputStream getOutputStream (InputStream is) throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        byte[] bs = new byte[is.available()];
+        int len;
+        while ((len = is.read(bs)) != -1) {
+            baos.write(bs, 0, len);
+        }
+        return baos;
+    }
+}
diff --git a/server/zhubo/src/main/java/com/doumee/api/business/BrandController.java b/server/zhubo/src/main/java/com/doumee/api/business/BrandController.java
new file mode 100644
index 0000000..586f3f8
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/api/business/BrandController.java
@@ -0,0 +1,41 @@
+package com.doumee.api.business;
+
+import com.doumee.api.BaseController;
+import com.doumee.core.annotation.excel.ExcelExporter;
+import com.doumee.core.annotation.pr.PreventRepeat;
+import com.doumee.core.model.ApiResponse;
+import com.doumee.core.model.LoginUserInfo;
+import com.doumee.core.model.PageData;
+import com.doumee.core.model.PageWrap;
+import com.doumee.dao.business.model.Brand;
+import com.doumee.service.business.BrandService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author 姹熻箘韫�
+ * @date 2023/05/12 13:58
+ */
+@Api(tags = "鍝佺墝淇℃伅琛�")
+@RestController
+@RequestMapping("/business/brand")
+public class BrandController extends BaseController {
+
+    @Autowired
+    private BrandService brandService;
+
+    @ApiOperation("鍒楄〃鏌ヨ")
+    @PostMapping("/list")
+    public ApiResponse<List<Brand>> findList (@RequestBody Brand brand) {
+        return ApiResponse.success(brandService.findList(brand));
+    }
+
+}
diff --git a/server/zhubo/src/main/java/com/doumee/api/business/CateBudgetController.java b/server/zhubo/src/main/java/com/doumee/api/business/CateBudgetController.java
new file mode 100644
index 0000000..a64325c
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/api/business/CateBudgetController.java
@@ -0,0 +1,36 @@
+package com.doumee.api.business;
+
+import com.doumee.api.BaseController;
+import com.doumee.core.annotation.pr.PreventRepeat;
+import com.doumee.core.model.ApiResponse;
+import com.doumee.core.model.PageData;
+import com.doumee.core.model.PageWrap;
+import com.doumee.dao.business.model.CateBudget;
+import com.doumee.service.business.CateBudgetService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * @author 姹熻箘韫�
+ * @since 2023/05/15 17:09
+ */
+@Api(tags = "鍝佺被浠锋牸鍖洪棿琛�")
+@RestController
+@RequestMapping("/business/cateBudget")
+public class CateBudgetController extends BaseController {
+
+    @Autowired
+    private CateBudgetService cateBudgetService;
+
+
+    @ApiOperation("鍒嗛〉鏌ヨ")
+    @PostMapping("/page")
+    @RequiresPermissions("business:catebudget:query")
+    public ApiResponse<PageData<CateBudget>> findPage (@RequestBody PageWrap<CateBudget> pageWrap) {
+        return ApiResponse.success(cateBudgetService.findPage(pageWrap));
+    }
+
+}
diff --git a/server/zhubo/src/main/java/com/doumee/api/business/CategoryController.java b/server/zhubo/src/main/java/com/doumee/api/business/CategoryController.java
new file mode 100644
index 0000000..508defc
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/api/business/CategoryController.java
@@ -0,0 +1,106 @@
+package com.doumee.api.business;
+
+import com.doumee.api.BaseController;
+import com.doumee.core.annotation.excel.ExcelExporter;
+import com.doumee.core.annotation.pr.PreventRepeat;
+import com.doumee.core.constants.ResponseStatus;
+import com.doumee.core.exception.BusinessException;
+import com.doumee.core.model.ApiResponse;
+import com.doumee.core.model.LoginUserInfo;
+import com.doumee.core.model.PageData;
+import com.doumee.core.model.PageWrap;
+import com.doumee.core.utils.Constants;
+import com.doumee.dao.business.model.BaseCateParam;
+import com.doumee.dao.business.model.BaseCategory;
+import com.doumee.dao.business.model.Category;
+import com.doumee.service.CateParamSelectService;
+import com.doumee.service.business.BaseCateParamService;
+import com.doumee.service.business.BaseCategoryService;
+import com.doumee.service.business.CategoryService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.java.Log;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * @author 姹熻箘韫�
+ * @date 2023/05/12 13:58
+ */
+@Api(tags = "鍝佺被淇℃伅琛�")
+@RestController
+@RequestMapping("/business/category")
+public class CategoryController extends BaseController {
+
+    @Autowired
+    private CategoryService categoryService;
+
+    @Autowired
+    private BaseCategoryService baseCategoryService;
+
+    @Autowired
+    private BaseCateParamService baseCateParamService;
+    @Autowired
+    private CateParamSelectService cateParamSelectService;
+
+
+    @ApiOperation("鍒楄〃")
+    @PostMapping("/list")
+    public ApiResponse<List<Category>> findList (@RequestBody Category category) {
+        return ApiResponse.success(categoryService.findList(category));
+    }
+
+    @ApiOperation("鍒楄〃 - 鍟嗗搧閫夋嫨")
+    @GetMapping("/findListForGoodsId")
+    public ApiResponse<List<Category>> findListForGoodsId (Integer goodsId) {
+        return ApiResponse.success(categoryService.findListForGoods(goodsId));
+    }
+
+
+    @ApiOperation("浼佷笟閫夋嫨鍒嗙被鍒楄〃 - H5")
+    @PostMapping("/companyFindList")
+    public ApiResponse<List<Category>> companyFindList (@RequestBody Category category) {
+        return ApiResponse.success(categoryService.companyFindList(category));
+    }
+
+    @ApiOperation("骞冲彴鍒嗙被鍒楄〃")
+    @PostMapping("/baseCategoryList")
+    public ApiResponse<List<BaseCategory>> baseCategoryList () {
+        BaseCategory baseCategory = new BaseCategory();
+        baseCategory.setIsdeleted(Constants.ZERO);
+        baseCategory.setStatus(Constants.ZERO);
+        List list = baseCategoryService.findList(baseCategory);
+        return ApiResponse.success(list);
+    }
+
+    @ApiOperation("骞冲彴鍒嗙被璇︽儏")
+    @GetMapping("/baseCategoryDetail")
+    public ApiResponse<BaseCategory> baseCategoryDetail (Integer baseCategoryId) {
+
+        BaseCategory baseCategory = baseCategoryService.findById(baseCategoryId);
+        if(Objects.isNull(baseCategory)){
+            throw new BusinessException(ResponseStatus.DATA_EMPTY);
+        }
+        BaseCateParam baseCateParam = new BaseCateParam();
+        baseCateParam.setIsdeleted(Constants.ZERO);
+        baseCateParam.setStatus(Constants.ZERO);
+        baseCateParam.setCategoryId(baseCategoryId);
+        baseCategory.setBaseCateParamList(
+                baseCateParamService.findList(baseCateParam)
+        );
+        return ApiResponse.success(baseCategory);
+    }
+
+    @ApiOperation("鍒楄〃 - SaaSH5")
+    @PostMapping("/saasList")
+    public ApiResponse<List<Category>> saasList (@RequestBody Category category) {
+        return ApiResponse.success(categoryService.findListSaaS(category));
+    }
+
+}
diff --git a/server/zhubo/src/main/java/com/doumee/api/business/GoodsController.java b/server/zhubo/src/main/java/com/doumee/api/business/GoodsController.java
new file mode 100644
index 0000000..f20fdd2
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/api/business/GoodsController.java
@@ -0,0 +1,71 @@
+package com.doumee.api.business;
+
+import com.doumee.api.BaseController;
+import com.doumee.core.annotation.excel.ExcelExporter;
+import com.doumee.core.annotation.pr.PreventRepeat;
+import com.doumee.core.model.LoginUserInfo;
+import com.doumee.core.model.PageData;
+import com.doumee.core.model.PageWrap;
+import com.doumee.dao.business.model.Goods;
+import com.doumee.dao.business.model.dto.BatchDisableDTO;
+import com.doumee.dao.business.model.dto.GoodCreatePlatRequest;
+import com.doumee.dao.business.model.dto.GoodsRequest;
+import com.doumee.service.CateParamSelectService;
+import com.doumee.service.business.GoodsService;
+import io.swagger.annotations.*;
+import lombok.extern.java.Log;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.doumee.core.model.ApiResponse;
+/**
+ * @author 姹熻箘韫�
+ * @date 2023/05/12 13:58
+ */
+@Api(tags = "鍟嗗搧淇℃伅琛�")
+@RestController
+@RequestMapping("/business/goods")
+public class GoodsController extends BaseController {
+
+    @Autowired
+    private GoodsService goodsService;
+    @Autowired
+    private CateParamSelectService cateParamSelectService;
+
+    @ApiOperation("鍒楄〃 - H5")
+    @PostMapping("/list")
+    public ApiResponse<List<Goods>> findList (@RequestBody Goods goods) {
+        LoginUserInfo user = (LoginUserInfo) SecurityUtils.getSubject().getPrincipal();
+        goods.setCompanyId(user.getCompanyId());
+        return ApiResponse.success(goodsService.findList(goods));
+    }
+
+
+    @ApiOperation("鍟嗗搧鍒嗛〉鍒楄〃 - H5")
+    @PostMapping("/goodsPage")
+    public ApiResponse<PageData<Goods>> goodsPage(@RequestBody PageWrap<GoodsRequest> pageWrap) {
+        return ApiResponse.success(goodsService.getGoodsPage(pageWrap));
+    }
+
+    @ApiOperation("鍒楄〃鏌ヨ - H5")
+    @PostMapping("/listForH5")
+    public ApiResponse<List<Goods>> listForH5 (@RequestBody GoodsRequest goodsRequest) {
+        return ApiResponse.success(goodsService.findListForH5(goodsRequest));
+    }
+
+    @ApiOperation("鑾峰彇H5棣栭〉鍥�")
+    @PostMapping("/h5Image")
+    public ApiResponse<String> h5Image () {
+        return ApiResponse.success(goodsService.h5Image());
+    }
+
+}
diff --git a/server/zhubo/src/main/java/com/doumee/api/business/WebParamController.java b/server/zhubo/src/main/java/com/doumee/api/business/WebParamController.java
new file mode 100644
index 0000000..47ef372
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/api/business/WebParamController.java
@@ -0,0 +1,48 @@
+package com.doumee.api.business;
+
+import com.doumee.api.BaseController;
+import com.doumee.core.annotation.excel.ExcelExporter;
+import com.doumee.core.annotation.pr.PreventRepeat;
+import com.doumee.core.model.ApiResponse;
+import com.doumee.core.model.PageWrap;
+import com.doumee.core.model.PageData;
+import com.doumee.dao.business.model.WebParam;
+import com.doumee.dao.system.dto.UpdateWebParamDTO;
+import com.doumee.service.business.WebParamService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.shiro.authz.annotation.RequiresPermissions;    
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import javax.servlet.http.HttpServletResponse;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author 姹熻箘韫�
+ * @since 2023/09/12 11:18
+ */
+@Api(tags = "浼佷笟椤甸潰閰嶇疆淇℃伅琛�")
+@RestController
+@RequestMapping("/business/webParam")
+public class WebParamController extends BaseController {
+
+    @Autowired
+    private WebParamService webParamService;
+
+
+    @ApiOperation("鑾峰彇褰撳墠鐧诲綍浼佷笟閰嶇疆淇℃伅")
+    @GetMapping("/getByLogin")
+    public ApiResponse<WebParam> getByLogin() {
+        return ApiResponse.success(webParamService.findOne());
+    }
+
+    @ApiOperation("鏇存柊浼佷笟閰嶇疆淇℃伅")
+    @PostMapping("/renew")
+    public ApiResponse renew(@RequestBody UpdateWebParamDTO updateWebParamDTO) {
+        webParamService.renew(updateWebParamDTO);
+        return ApiResponse.success("鎿嶄綔鎴愬姛");
+    }
+
+}
diff --git a/server/zhubo/src/main/java/com/doumee/api/system/SystemController.java b/server/zhubo/src/main/java/com/doumee/api/system/SystemController.java
new file mode 100644
index 0000000..6e49f7f
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/api/system/SystemController.java
@@ -0,0 +1,66 @@
+package com.doumee.api.system;
+
+import com.doumee.api.BaseController;
+import com.doumee.biz.system.SystemUserBiz;
+import com.doumee.core.annotation.pr.PreventRepeat;
+import com.doumee.core.annotation.trace.Trace;
+import com.doumee.core.model.ApiResponse;
+import com.doumee.core.model.LoginUserInfo;
+import com.doumee.core.utils.Constants;
+import com.doumee.dao.system.dto.LoginDTO;
+import com.doumee.dao.system.dto.UpdatePwdDto;
+import com.doumee.dao.system.dto.WebLoginDTO;
+import com.doumee.service.system.SystemLoginService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.subject.Subject;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * @author Eva.Caesar Liu
+ * @date 2023/03/21 14:49
+ */
+@Api(tags = "绯荤粺鍔熻兘")
+@Trace(exclude = true)
+@Slf4j
+@RestController
+@RequestMapping("/system")
+public class SystemController extends BaseController {
+
+    @Autowired
+    private SystemUserBiz systemUserBiz;
+
+    @Autowired
+    private SystemLoginService systemLoginService;
+
+
+    @PreventRepeat(limit = 10, lockTime = 10000)
+    @ApiOperation("鐧诲綍 - H5")
+    @PostMapping("/loginH5")
+    public ApiResponse<String> loginH5 (@Validated @RequestBody WebLoginDTO dto, HttpServletRequest request) {
+        LoginDTO loginDTO = new LoginDTO();
+        BeanUtils.copyProperties(dto,loginDTO);
+        return ApiResponse.success(systemLoginService.loginByPassword(loginDTO, Constants.TWO, request));
+    }
+
+    @ApiOperation("閫�鍑虹櫥褰�")
+    @PostMapping("/logout")
+    public ApiResponse logout () {
+        Subject subject = SecurityUtils.getSubject();
+        subject.logout();
+        return ApiResponse.success(null);
+    }
+    @ApiOperation("鑾峰彇褰撳墠鐧诲綍鐨勭敤鎴蜂俊鎭�")
+    @GetMapping("/getUserInfo")
+    public ApiResponse<LoginUserInfo> getUserInfo () {
+        return ApiResponse.success(this.getLoginUser());
+    }
+}
diff --git a/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroAuthFilter.java b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroAuthFilter.java
new file mode 100644
index 0000000..6f3cca8
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroAuthFilter.java
@@ -0,0 +1,144 @@
+package com.doumee.config.shiro;
+
+import com.alibaba.fastjson.JSON;
+import com.doumee.core.model.ApiResponse;
+import com.doumee.core.model.LoginUserInfo;
+import com.doumee.core.utils.Constants;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shiro.cache.Cache;
+import org.apache.shiro.cache.MapCache;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.session.mgt.DefaultSessionKey;
+import org.apache.shiro.session.mgt.SessionManager;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
+import org.springframework.http.HttpStatus;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+import java.io.Serializable;
+import java.util.Deque;
+import java.util.LinkedList;
+
+/**
+ * Shiro璁よ瘉杩囨护鍣紝澶勭悊鏈璇佹儏鍐电殑鍝嶅簲
+ * @author Eva.Caesar Liu
+ * @date 2023/04/17 12:11
+ */
+public class ShiroAuthFilter extends FormAuthenticationFilter {
+
+    public ShiroAuthFilter(SessionManager sessionManager,ShiroCacheManager shiroCacheManager) {
+        super();
+        this.sessionManager =   (ShiroSessionManager)sessionManager;
+        this.cache = shiroCacheManager.getCache("shiro_redis_cache");
+    }
+    @Override
+    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)  {
+        return false;
+    }
+
+    private int maxSession = 1; //鏈�澶т細璇濇暟閲�
+
+    private boolean kickOutAfter = false;   //韪㈠嚭鍓嶈�呰繕鏄悗鑰�
+    private Cache<String, Deque<Serializable>> cache; //缂撳瓨绠$悊
+
+
+    private ShiroSessionManager sessionManager;  //浼氳瘽绠$悊
+
+    @Override
+    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
+        Subject subject = getSubject(request, response);
+        if (!subject.isAuthenticated() && !subject.isRemembered()) { //濡傛灉涓嶆槸璁よ瘉杩囧拰璁颁綇瀵嗙爜鐨勶紝灏辩洿鎺ユ斁琛岃姹傦紝閬垮厤閫犳垚璁块棶杩囨參
+           // return Boolean.TRUE;
+        }
+        Session session = subject.getSession(); //鑾峰彇浼氳瘽session
+        Object principal = subject.getPrincipal();
+        Serializable sessionId = session.getId();
+        LoginUserInfo userInfo = (LoginUserInfo) principal;
+        if(userInfo == null || !Constants.equalsInteger(userInfo.getType(), Constants.UserType.ZHUBO.getKey()) ){
+            HttpServletResponse servletResponse = (HttpServletResponse) response;
+            servletResponse.setHeader("content-type", "application/json;charset=UTF-8");
+            servletResponse.getWriter().write(JSON.toJSONString(ApiResponse.failed(HttpStatus.UNAUTHORIZED.value(), "鏈櫥褰曟垨鐧诲綍淇℃伅宸茶繃鏈�")));
+            return Boolean.FALSE;
+        }
+        String userName = userInfo.getCompanyId() +"_"+ userInfo.getId();
+        Deque<Serializable> deque = cache.get(userName);
+        if (deque == null) {
+            deque = new LinkedList<>();
+        }
+        if (!deque.contains(sessionId) && session.getAttribute("kickOut") == null) {
+            deque.push(sessionId);
+            cache.put(userName, deque);
+        }
+        while (deque.size() > maxSession) {
+            Serializable kickOutSessionId;
+            if (kickOutAfter) {
+                kickOutSessionId = deque.removeFirst();
+                cache.put(userName, deque);
+            } else {
+                kickOutSessionId = deque.removeLast();
+                cache.put(userName, deque);
+            }
+
+            try {
+                Session kickOutSession = sessionManager.getSession(new DefaultSessionKey(kickOutSessionId));
+                if (kickOutSession != null){
+                    kickOutSession.setAttribute("kickOut", Boolean.TRUE);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        if (session!=null && session.getAttribute("kickOut") != null && (Boolean) session.getAttribute("kickOut") == true) {
+            try {
+                subject.logout();
+                if(deque!=null){
+                    deque.remove(sessionId);
+                    cache.put(userName, deque);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            saveRequest(request);
+            HttpServletResponse servletResponse = (HttpServletResponse) response;
+            servletResponse.setHeader("content-type", "application/json;charset=UTF-8");
+            servletResponse.getWriter().write(JSON.toJSONString(ApiResponse.failed(HttpStatus.UNAUTHORIZED.value(), "鏈櫥褰曟垨鐧诲綍淇℃伅宸茶繃鏈�")));
+            return Boolean.FALSE;
+        }
+        return Boolean.TRUE;
+    }
+
+    public int getMaxSession() {
+        return maxSession;
+    }
+
+    public void setMaxSession(int maxSession) {
+        this.maxSession = maxSession;
+    }
+
+    public boolean isKickOutAfter() {
+        return kickOutAfter;
+    }
+
+    public void setKickOutAfter(boolean kickOutAfter) {
+        this.kickOutAfter = kickOutAfter;
+    }
+
+    public Cache<String, Deque<Serializable>> getCache() {
+        return cache;
+    }
+
+    public void setCache(Cache<String, Deque<Serializable>> cache) {
+        this.cache = cache;
+    }
+
+    public ShiroSessionManager getSessionManager() {
+        return sessionManager;
+    }
+
+    public void setSessionManager(ShiroSessionManager sessionManager) {
+        this.sessionManager = sessionManager;
+    }
+}
diff --git a/server/company/src/main/java/com/doumee/config/shiro/ShiroAuthFilter2.java b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroAuthFilter2.java
similarity index 100%
rename from server/company/src/main/java/com/doumee/config/shiro/ShiroAuthFilter2.java
rename to server/zhubo/src/main/java/com/doumee/config/shiro/ShiroAuthFilter2.java
diff --git a/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroCache.java b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroCache.java
new file mode 100644
index 0000000..6fe6153
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroCache.java
@@ -0,0 +1,163 @@
+package com.doumee.config.shiro;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.cache.Cache;
+import org.apache.shiro.cache.CacheException;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.apache.shiro.util.CollectionUtils;
+import org.springframework.context.annotation.Scope;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.SerializationException;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Shiro缂撳瓨
+ * @author Eva.Caesar Liu
+ * @date 2023/04/17 12:11
+ */
+@Scope(value = "prototype")
+@Slf4j
+@Component
+public class ShiroCache implements Cache<Object, Serializable> {
+
+    private String keyPrefix = "ProSelect";
+
+    @Resource(name="sessionRedisTemplate")
+    private RedisTemplate<Object, Serializable> redisTemplate;
+
+    public ShiroCache () {
+        log.debug("ShiroCache: new, keyPrefix = [" + keyPrefix + "]");
+    }
+
+    public ShiroCache(String keyPrefix) {
+        log.debug("ShiroCache: new, keyPrefix = [" + keyPrefix + "]");
+        this.keyPrefix = keyPrefix;
+    }
+
+    @Override
+    public Serializable get(Object key) throws CacheException {
+        if (key == null) {
+            return null;
+        }
+        return redisTemplate.opsForValue().get(getKey(key));
+    }
+
+    @Override
+    public Serializable put(Object key, Serializable value) throws CacheException {
+        if (key == null) {
+            return null;
+        }
+        redisTemplate.opsForValue().set(getKey(key), value);
+        return value;
+    }
+
+    public Serializable put(Object key, Serializable value, int timeout) throws CacheException {
+        if (key == null) {
+            return null;
+        }
+        try {
+            redisTemplate.opsForValue().set(getKey(key), value, timeout, TimeUnit.SECONDS);
+        }catch (Exception e){
+
+        }
+        return value;
+    }
+
+    @Override
+    public void clear() throws CacheException {
+        Set<Object> keys = this.keys();
+        redisTemplate.delete(keys);
+    }
+
+    @Override
+    public int size() {
+        return this.keys().size();
+    }
+
+    @Override
+    public Set<Object> keys() {
+        Set<Object> keys = redisTemplate.keys(keyPrefix + "*");
+        if (CollectionUtils.isEmpty(keys)) {
+            return Collections.emptySet();
+        }
+        return keys;
+    }
+
+    @Override
+    public Collection<Serializable> values() {
+        Collection<Serializable> values = new ArrayList<>();
+        Set<Object> keys = this.keys();
+        if (CollectionUtils.isEmpty(keys)) {
+            return values;
+        }
+        for (Object k : keys) {
+            values.add(redisTemplate.opsForValue().get(k));
+        }
+        return values;
+    }
+
+    @Override
+    public Serializable remove(Object key) throws CacheException {
+        if (key == null) {
+            return null;
+        }
+        Serializable value = this.get(getKey(key));
+        redisTemplate.delete(getKey(key));
+        return value;
+    }
+
+    private Object getKey (Object key) {
+        if (key instanceof PrincipalCollection) {
+            return this.keyPrefix + getRedisKeyFromPrincipalIdField((PrincipalCollection)key);
+        }
+        return (key instanceof String ? (this.keyPrefix + key) : key);
+    }
+
+    /**
+     * 鑾峰彇redis cache key
+     */
+    private String getRedisKeyFromPrincipalIdField(PrincipalCollection key) {
+        Object principalObject = key.getPrimaryPrincipal();
+        if (principalObject instanceof String) {
+            return principalObject.toString();
+        } else {
+            Method pincipalIdGetter = this.getPrincipalIdGetter(principalObject);
+            return this.getIdObj(principalObject, pincipalIdGetter);
+        }
+    }
+
+    private Method getPrincipalIdGetter(Object principalObject) {
+        Method pincipalIdGetter;
+        String principalIdMethodName = this.getPrincipalIdMethodName();
+
+        try {
+            pincipalIdGetter = principalObject.getClass().getMethod(principalIdMethodName);
+            return pincipalIdGetter;
+        } catch (NoSuchMethodException e) {
+            throw new SerializationException(e.getMessage(), e);
+        }
+    }
+
+    private String getIdObj(Object principalObject, Method pincipalIdGetter) {
+        try {
+            Object idObj = pincipalIdGetter.invoke(principalObject);
+            String redisKey = idObj.toString();
+            return redisKey;
+        } catch (Exception e) {
+            throw new SerializationException(e.getMessage(), e);
+        }
+    }
+
+    private String getPrincipalIdMethodName() {
+        return "getId";
+    }
+}
diff --git a/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroCacheManager.java b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroCacheManager.java
new file mode 100644
index 0000000..4c11155
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroCacheManager.java
@@ -0,0 +1,44 @@
+package com.doumee.config.shiro;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.cache.Cache;
+import org.apache.shiro.cache.CacheException;
+import org.apache.shiro.cache.CacheManager;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * 鑷畾涔塖hiro CacheManager
+ * @author Eva.Caesar Liu
+ * @date 2023/04/17 12:11
+ */
+@Slf4j
+@Component
+public class ShiroCacheManager implements CacheManager {
+
+    private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap();
+
+    private static ApplicationContext applicationContext;
+
+    @Override
+    public <K, V> Cache<K, V> getCache(String name) throws CacheException {
+        log.debug("get cache, name=" + name);
+        Cache cache = this.caches.get(name);
+        if (cache == null) {
+            cache = applicationContext.getBean(ShiroCache.class, "shiro:cache:");
+            this.caches.put(name, cache);
+        }
+        return cache;
+    }
+
+    @Autowired
+    public void setApplicationContext (ApplicationContext applicationContext) {
+        if (ShiroCacheManager.applicationContext == null) {
+            ShiroCacheManager.applicationContext = applicationContext;
+        }
+    }
+}
diff --git a/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroConfig.java b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroConfig.java
new file mode 100644
index 0000000..d9636c8
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroConfig.java
@@ -0,0 +1,153 @@
+package com.doumee.config.shiro;
+
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.session.mgt.SessionManager;
+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.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+import javax.servlet.Filter;
+import java.io.Serializable;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Shiro閰嶇疆
+ * @author Eva.Caesar Liu
+ * @date 2023/04/17 12:11
+ */
+@Configuration
+public class ShiroConfig {
+
+    @Value("${cache.session.expire}")
+    private int sessionExpireTime;
+
+    @Autowired
+    private ShiroCredentialsMatcher shiroCredentialsMatcher;
+
+    @Autowired
+    private ShiroSessionDAO shiroSessionDAO;
+
+    @Autowired
+    private ShiroCacheManager shiroCacheManager;
+
+    @Autowired
+    private ShiroRealm shiroRealm;
+
+    @Bean("sessionRedisTemplate")
+    public RedisTemplate<Object, Serializable> sessionRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
+        RedisTemplate<Object, Serializable> redisTemplate = new RedisTemplate<>();
+        redisTemplate.setConnectionFactory(redisConnectionFactory);
+        // 榛樿搴忓垪鍖栨柟寮�
+        redisTemplate.setDefaultSerializer(new StringRedisSerializer());
+        // 鍊煎簭鍒楀寲鏂瑰紡
+        ShiroSessionSerializer serializer = new ShiroSessionSerializer();
+        redisTemplate.setValueSerializer(serializer);
+        redisTemplate.setHashValueSerializer(serializer);
+        redisTemplate.afterPropertiesSet();
+        return redisTemplate;
+    }
+
+    @Bean
+    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
+        DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
+        autoProxyCreator.setProxyTargetClass(true);
+        return autoProxyCreator;
+    }
+
+    @Bean
+    public SessionManager sessionManager() {
+        ShiroSessionManager sessionManager = new ShiroSessionManager();
+        sessionManager.setSessionDAO(shiroSessionDAO);
+        sessionManager.setGlobalSessionTimeout(sessionExpireTime*1000);
+        // 鍒犻櫎澶辨晥鐨剆ession
+        sessionManager.setDeleteInvalidSessions(true);
+        return sessionManager;
+    }
+
+    @Bean
+    public SecurityManager securityManager() {
+        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
+        securityManager.setRealm(shiroRealm);
+        securityManager.setSessionManager(this.sessionManager());
+        securityManager.setCacheManager(shiroCacheManager);
+        return securityManager;
+    }
+
+    @Bean
+    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
+        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
+        shiroFilterFactoryBean.setSecurityManager(securityManager);
+        Map<String, String> map = new LinkedHashMap<>();
+        // 璺緞鎷︽埅閰嶇疆
+        // 璺緞鎷︽埅閰嶇疆
+//        map.put("/system/dictData/companyUserRules","anon");
+//        map.put("/system/login", "anon");
+//        map.put("/system/logout", "anon");
+//        map.put("/common/captcha", "anon");
+//        map.put("/business/areas/*", "anon");
+//        map.put("/public/uploadPicture","anon");
+//        map.put("/public/uploadLocal","anon");
+
+        map.put("/system/dictData/companyUserRules","anon");
+        map.put("/system/login", "anon");
+        map.put("/system/logout", "anon");
+        map.put("/system/loginH5", "anon");
+        map.put("/common/captcha", "anon");
+        map.put("/business/areas/*", "anon");
+        map.put("/public/uploadPicture","anon");
+        map.put("/public/uploadLocal","anon");
+
+
+//        map.put("/business/company/register", "anon");
+//        map.put("/business/labels/page","anon");
+//        map.put("/business/*/list","anon");
+//        map.put("/business/goods/goodsPage","anon");
+//        map.put("/business/goods/h5Image","anon");
+//        map.put("/business/goods/export","anon");
+//        map.put("/business/goods/listForH5","anon");
+
+
+        // - 鏀捐swagger
+        map.put("/doc.html", "anon");
+        map.put("/webjars/**", "anon");
+        map.put("/swagger-resources/**", "anon");
+        map.put("/v2/api-docs/**", "anon");
+
+        // - 鍏朵粬鎺ュ彛缁熶竴鎷︽埅
+        map.put("/**", "authc");
+        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
+        // 娣诲姞璁よ瘉杩囨护鍣�
+        Map<String, Filter> filters = new LinkedHashMap<>();
+        filters.put("authc", new ShiroAuthFilter(this.sessionManager(),shiroCacheManager));
+        shiroFilterFactoryBean.setFilters(filters);
+        return shiroFilterFactoryBean;
+    }
+
+    @Bean
+    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
+        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
+        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
+        return authorizationAttributeSourceAdvisor;
+    }
+
+    @Bean
+    public ShiroSessionDAO getShiroSessionDAO () {
+        shiroSessionDAO.setExpireTime(sessionExpireTime);
+        return shiroSessionDAO;
+    }
+
+    @Bean
+    public ShiroRealm getShiroRealm () {
+        shiroRealm.setCredentialsMatcher(shiroCredentialsMatcher);
+        return shiroRealm;
+    }
+}
diff --git a/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroCredentialsMatcher.java b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroCredentialsMatcher.java
new file mode 100644
index 0000000..8550e9d
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroCredentialsMatcher.java
@@ -0,0 +1,46 @@
+package com.doumee.config.shiro;
+
+import com.doumee.core.utils.Utils;
+import com.doumee.dao.system.model.SystemUser;
+import com.doumee.service.system.SystemUserService;
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+/**
+ * Shiro瀵嗙爜姣斿澶勭悊
+ * @author Eva.Caesar Liu
+ * @date 2023/04/17 12:11
+ */
+@Component
+public class ShiroCredentialsMatcher extends HashedCredentialsMatcher {
+    @Lazy
+    @Autowired
+    private SystemUserService systemUserService;
+
+    @Override
+    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
+        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
+        SystemUser queryUserDto = new SystemUser();
+        queryUserDto.setUsername(usernamePasswordToken.getUsername());
+        queryUserDto.setDeleted(Boolean.FALSE);
+        SystemUser systemUser = systemUserService.findOne(queryUserDto);
+        if (systemUser == null) {
+            return Boolean.FALSE;
+        }
+//        if(usernamePasswordToken.getDdLogin()){
+//            return Boolean.TRUE;
+//        }
+//        if(usernamePasswordToken.getWxLogin()){
+//            return Boolean.TRUE;
+//        }
+        // 鍔犲瘑瀵嗙爜
+        String pwd = Utils.Secure.encryptPassword(new String(usernamePasswordToken.getPassword()), systemUser.getSalt());
+        // 姣旇緝瀵嗙爜
+        return this.equals(pwd, systemUser.getPassword());
+    }
+}
diff --git a/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroRealm.java b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroRealm.java
new file mode 100644
index 0000000..c4cae4d
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroRealm.java
@@ -0,0 +1,115 @@
+package com.doumee.config.shiro;
+
+import com.doumee.core.constants.ResponseStatus;
+import com.doumee.core.exception.BusinessException;
+import com.doumee.core.model.LoginUserInfo;
+import com.doumee.core.utils.Constants;
+import com.doumee.core.utils.DateUtil;
+import com.doumee.dao.business.model.Company;
+import com.doumee.dao.system.model.SystemPermission;
+import com.doumee.dao.system.model.SystemRole;
+import com.doumee.dao.system.model.SystemUser;
+import com.doumee.service.business.CompanyService;
+import com.doumee.service.system.SystemDataPermissionService;
+import com.doumee.service.system.SystemPermissionService;
+import com.doumee.service.system.SystemRoleService;
+import com.doumee.service.system.SystemUserService;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.SimpleAuthenticationInfo;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.authz.SimpleAuthorizationInfo;
+import org.apache.shiro.realm.AuthorizingRealm;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 鑷畾涔塕ealm锛屽鐞嗚璇佸拰鏉冮檺
+ * @author Eva.Caesar Liu
+ * @date 2022/03/15 09:54
+ */
+@Component
+public class ShiroRealm extends AuthorizingRealm {
+
+    @Lazy
+    @Autowired
+    private SystemDataPermissionService systemDataPermissionService;
+    @Lazy
+    @Autowired
+    private SystemUserService systemUserService;
+
+    @Lazy
+    @Autowired
+    private SystemRoleService systemRoleService;
+
+    @Lazy
+    @Autowired
+    private SystemPermissionService systemPermissionService;
+
+    @Lazy
+    @Autowired
+    private CompanyService companyService;
+
+    /**
+     * 鏉冮檺澶勭悊
+     * @author Eva.Caesar Liu
+     * @date 2022/03/15 09:54
+     */
+    @Override
+    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
+        LoginUserInfo loginUserInfo = (LoginUserInfo)principalCollection.getPrimaryPrincipal();
+        // 璁剧疆鐢ㄦ埛瑙掕壊鍜屾潈闄�
+        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
+        authorizationInfo.addRoles(loginUserInfo.getRoles());
+        authorizationInfo.addStringPermissions(loginUserInfo.getPermissions());
+        return authorizationInfo;
+    }
+
+    /**
+     * 璁よ瘉澶勭悊
+     * @author Eva.Caesar Liu
+     * @date 2022/03/15 09:54
+     */
+    @Override
+    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException{
+        // 鑾峰彇鐢ㄦ埛鍚�
+        String username = authenticationToken.getPrincipal().toString();
+        // 鏍规嵁鐢ㄦ埛鍚嶆煡璇㈢敤鎴峰璞�
+        SystemUser queryDto = new SystemUser();
+        queryDto.setUsername(username);
+        queryDto.setDeleted(Boolean.FALSE);
+        SystemUser user = systemUserService.findOne(queryDto);
+        if(user == null){
+            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"瀵逛笉璧凤紝璐﹀彿鎴栧瘑鐮佷笉姝g‘锛�");
+        }
+        if( !Constants.equalsInteger(user.getType(),Constants.UserType.ZHUBO.getKey())){
+            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"瀵逛笉璧凤紝闈炰富鎾处鎴疯韩浠斤紝濡傛湁鐤戦棶璇疯仈绯荤郴缁熺鐞嗗憳锛侊紒");
+        }
+        if(!Constants.equalsInteger(user.getStatus(),Constants.ZERO)){
+            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"瀵逛笉璧凤紝璐﹀彿淇℃伅宸茶绂佺敤锛屽鏈夌枒闂鑱旂郴绯荤粺绠$悊鍛橈紒");
+        }
+        if(!user.getType().equals(Constants.UserType.SYSTEM)){
+            Company company = companyService.findById(user.getCompanyId());
+            if(company.getStatus().equals(Constants.ONE)){
+                throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"瀵逛笉璧凤紝浼佷笟淇℃伅宸茶绂佺敤锛屽鏈夌枒闂鑱旂郴绯荤粺绠$悊鍛橈紒");
+            }
+            if(DateUtil.compareDate(new Date(),DateUtil.addDaysToDate(company.getOepnValidDate(),1))<=Constants.ZERO){
+                throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"浼佷笟璐﹀彿宸茶繃鏈燂紝濡傞渶缁х画浣跨敤锛岃鑱旂郴鎮ㄧ殑涓氬姟缁忕悊");
+            }
+            user.setCompany(company);
+        }
+        // 鑾峰彇鐧诲綍鐢ㄦ埛淇℃伅
+        List<SystemRole> roles = systemRoleService.findByUserId(user.getId());
+        List<SystemPermission> permissions = systemPermissionService.findByUserId(user.getId());
+        LoginUserInfo userInfo = LoginUserInfo.from(user, roles, permissions);
+        // 楠岃瘉鐢ㄦ埛
+        return new SimpleAuthenticationInfo(userInfo, user.getPassword(), this.getName());
+    }
+
+}
diff --git a/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroSessionDAO.java b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroSessionDAO.java
new file mode 100644
index 0000000..352aaed
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroSessionDAO.java
@@ -0,0 +1,113 @@
+package com.doumee.config.shiro;
+
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.session.UnknownSessionException;
+import org.apache.shiro.session.mgt.SimpleSession;
+import org.apache.shiro.session.mgt.eis.SessionDAO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * 鑷畾涔塖hiro SessionDAO锛屽皢浼氳瘽淇℃伅瀛樺叆缂撳瓨涓�
+ * @author Eva.Caesar Liu
+ * @date 2023/04/17 12:11
+ */
+@Data
+@Slf4j
+@Component
+public class ShiroSessionDAO implements SessionDAO {
+
+    private static final String KEY_PREFIX = "shiro:zhubo:session:";
+
+    @Autowired
+    private ShiroCache shiroCache;
+
+    private int expireTime = 60 * 60 * 24;
+
+    @Autowired
+    private ShiroTokenManager shiroTokenManager;
+
+    @Override
+    public Serializable create(Session session) {
+        if (session == null) {
+            log.error("session is null");
+            throw new UnknownSessionException("session is null");
+        }
+        Serializable sessionId = shiroTokenManager.build();
+        ((SimpleSession)session).setId(sessionId);
+        this.saveSession(session);
+        return sessionId;
+    }
+
+    @Override
+    public Session readSession(Serializable sessionId) throws UnknownSessionException{
+        if (sessionId == null) {
+            log.warn("session id is null");
+            return null;
+        }
+        if (sessionId instanceof String) {
+            // 瀵筍essionId杩涜楠岃瘉锛堝彲鐢ㄤ簬闃叉Session鎹曡幏銆佹毚鍔涙崟鎹夌瓑涓�绯诲垪瀹夊叏闂锛屾渶缁堝畨鍏ㄦ�у彇鍐充簬check濡備綍瀹炵幇锛�
+            shiroTokenManager.check((String) sessionId);
+        }
+        log.debug("read session from cache");
+        Session session = getSessionFromCache(sessionId);
+        if (session == null) {
+            throw new UnknownSessionException("There is no session with id [" + sessionId + "]");
+        }
+        return session;
+    }
+
+    @Override
+    public void update(Session session) throws UnknownSessionException {
+        this.saveSession(session);
+    }
+
+    @Override
+    public void delete(Session session) {
+        if (session != null && session.getId() != null) {
+            shiroCache.remove(KEY_PREFIX + session.getId());
+        }
+    }
+
+    @Override
+    public Collection<Session> getActiveSessions() {
+        Set<Session> sessions = new HashSet<>();
+        Set<Object> keys = shiroCache.keys();
+        if (keys != null && keys.size() > 0) {
+            Iterator iter = keys.iterator();
+            while(iter.hasNext()) {
+                sessions.add((Session) shiroCache.get(iter.next()));
+            }
+        }
+        return sessions;
+    }
+
+    private void saveSession(Session session) throws UnknownSessionException {
+        if (session == null || session.getId() == null) {
+            log.error("session or session id is null");
+            throw new UnknownSessionException("session or session id is null");
+        }
+        shiroCache.put(KEY_PREFIX + session.getId(), (SimpleSession)session, expireTime);
+    }
+
+    private Session getSessionFromCache (Serializable sessionId) {
+        Serializable object = shiroCache.get(KEY_PREFIX + sessionId);
+        Session session = null;
+        if (object != null) {
+            session = (Session)shiroCache.get(KEY_PREFIX + sessionId);
+        }
+        return session;
+    }
+
+    public void setExpireTime (int expireTime) {
+        this.expireTime = expireTime;
+    }
+}
diff --git a/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroSessionManager.java b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroSessionManager.java
new file mode 100644
index 0000000..bb2dd31
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroSessionManager.java
@@ -0,0 +1,85 @@
+package com.doumee.config.shiro;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.session.mgt.DefaultSessionManager;
+import org.apache.shiro.session.mgt.SessionContext;
+import org.apache.shiro.session.mgt.SessionKey;
+import org.apache.shiro.web.servlet.Cookie;
+import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
+import org.apache.shiro.web.servlet.SimpleCookie;
+import org.apache.shiro.web.session.mgt.WebSessionManager;
+import org.apache.shiro.web.util.WebUtils;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.Serializable;
+
+/**
+ * 鑷畾涔変細璇濈鐞嗗櫒
+ * @author Eva.Caesar Liu
+ * @date 2023/04/17 12:11
+ */
+@Slf4j
+public class ShiroSessionManager extends DefaultSessionManager implements WebSessionManager {
+
+    private static final String AUTH_TOKEN = "zhubo-auth-token";
+
+    @Override
+    protected void onStart(Session session, SessionContext context) {
+        super.onStart(session, context);
+        if (!WebUtils.isHttp(context)) {
+            log.debug("SessionContext argument is not Http compatible or does not have an Http request/response pair. No session ID cookie will be set.");
+            return;
+        }
+        HttpServletRequest request = WebUtils.getHttpRequest(context);
+        HttpServletResponse response = WebUtils.getHttpResponse(context);
+        Serializable sessionId = session.getId();
+        this.storeSessionId(sessionId, request, response);
+        request.removeAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE);
+        request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_IS_NEW, Boolean.TRUE);
+    }
+
+    @Override
+    public Serializable getSessionId(SessionKey key) {
+        Serializable sessionId = super.getSessionId(key);
+        if (sessionId == null && WebUtils.isWeb(key)) {
+            ServletRequest servletRequest = WebUtils.getRequest(key);
+            if (!(servletRequest instanceof HttpServletRequest)) {
+                log.trace("Can not get sessionId from header, the request is not HttpServletRequest");
+                return null;
+            }
+            HttpServletRequest request = (HttpServletRequest) servletRequest;
+            // 浠巆ookie涓幏鍙栬璇�
+            javax.servlet.http.Cookie[] cookies = request.getCookies();
+            if (cookies != null) {
+                for (javax.servlet.http.Cookie cookie : cookies) {
+                    if (AUTH_TOKEN.equals(cookie.getName())) {
+                        return cookie.getValue();
+                    }
+                }
+            }
+            // 浠巋eader涓幏鍙栬璇�
+            return request.getHeader(AUTH_TOKEN);
+        }
+        return sessionId;
+    }
+    @Override
+    public boolean isServletContainerSessions() {
+        return false;
+    }
+
+    private void storeSessionId(Serializable currentId, HttpServletRequest request, HttpServletResponse response) {
+        if (currentId == null) {
+            String msg = "sessionId cannot be null when persisting for subsequent requests.";
+            throw new IllegalArgumentException(msg);
+        }
+        Cookie cookie = new SimpleCookie(AUTH_TOKEN);
+        cookie.setHttpOnly(false);
+        String idString = currentId.toString();
+        cookie.setValue(idString);
+        cookie.saveTo(request, response);
+        log.trace("Set session ID cookie for session with id {}", idString);
+    }
+}
diff --git a/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroSessionSerializer.java b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroSessionSerializer.java
new file mode 100644
index 0000000..d334adf
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroSessionSerializer.java
@@ -0,0 +1,36 @@
+package com.doumee.config.shiro;
+
+import org.apache.commons.lang3.SerializationUtils;
+import org.apache.shiro.codec.Base64;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.SerializationException;
+
+import java.io.Serializable;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Session搴忓垪鍖�
+ * @author Eva.Caesar Liu
+ * @date 2023/04/17 12:11
+ */
+public class ShiroSessionSerializer implements RedisSerializer<Serializable> {
+
+    @Override
+    public byte[] serialize(Serializable obj) throws SerializationException {
+        if (obj == null) {
+            return new byte[0];
+        }
+        String sessionBase64 = Base64.encodeToString(SerializationUtils.serialize(obj));
+        return sessionBase64.getBytes(StandardCharsets.UTF_8);
+    }
+
+    @Override
+    public Serializable deserialize(byte[] bytes) throws SerializationException {
+        if (bytes == null || bytes.length == 0) {
+            return null;
+        }
+        String sessionString = new String(bytes, StandardCharsets.UTF_8);
+        byte[] sessionBytes = Base64.decode(sessionString);
+        return SerializationUtils.deserialize(sessionBytes);
+    }
+}
diff --git a/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroToken.java b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroToken.java
new file mode 100644
index 0000000..74c09df
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroToken.java
@@ -0,0 +1,54 @@
+package com.doumee.config.shiro;
+
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.springframework.stereotype.Component;
+
+/**
+ * 鑷畾涔塗oken 锛屽鐞嗚璇佸拰鏉冮檺
+ * @author Eva.Caesar Liu
+ * @date 2022/04/18 18:12
+ */
+@Component
+public class ShiroToken extends UsernamePasswordToken {
+
+    /**
+     * 鍏徃ID
+     */
+    Integer companyId;
+    Boolean isDdLogin;
+    Boolean isWxLogin;
+
+    public ShiroToken() {
+    }
+    public ShiroToken(Integer companyId, String username, String password, boolean isDdLogin, boolean isWxLogin) {
+        super(username,  password, false, (String)null);
+        this.companyId = companyId;
+        this.isDdLogin = isDdLogin;
+        this.isWxLogin = isWxLogin;
+    }
+
+    public Boolean getDdLogin() {
+        return isDdLogin;
+    }
+
+    public void setDdLogin(Boolean ddLogin) {
+        isDdLogin = ddLogin;
+    }
+
+
+    public Boolean getWxLogin() {
+        return isWxLogin;
+    }
+
+    public void setWxLogin(Boolean wxLogin) {
+        isWxLogin = wxLogin;
+    }
+
+    public Integer getCompanyId() {
+        return companyId;
+    }
+
+    public void setCompanyId(Integer companyId) {
+        this.companyId = companyId;
+    }
+}
diff --git a/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroTokenManager.java b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroTokenManager.java
new file mode 100644
index 0000000..ba35da6
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/config/shiro/ShiroTokenManager.java
@@ -0,0 +1,25 @@
+package com.doumee.config.shiro;
+
+import com.doumee.core.exception.UnSafeSessionException;
+import org.springframework.stereotype.Component;
+
+import java.util.UUID;
+
+/**
+ * 榛樿Token绠$悊鍣�
+ * @author Eva.Caesar Liu
+ * @date 2023/04/17 12:11
+ */
+@Component
+public class ShiroTokenManager {
+
+    String build() {
+        return UUID.randomUUID().toString();
+    }
+
+    void check(String token) throws UnSafeSessionException {
+        if (token == null || token.length() != 36) {
+            throw new UnSafeSessionException();
+        }
+    }
+}
diff --git a/server/zhubo/src/main/java/com/doumee/config/swagger/SwaggerConfig.java b/server/zhubo/src/main/java/com/doumee/config/swagger/SwaggerConfig.java
new file mode 100644
index 0000000..34caca8
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/config/swagger/SwaggerConfig.java
@@ -0,0 +1,88 @@
+package com.doumee.config.swagger;
+
+import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.RequestHandler;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.oas.annotations.EnableOpenApi;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+
+import java.util.function.Predicate;
+
+/**
+ * Swagger閰嶇疆
+ * @author Eva.Caesar Liu
+ * @date 2022/03/11 10:24
+ */
+@Configuration
+@EnableOpenApi
+@EnableKnife4j
+public class SwaggerConfig {
+
+    @Value("${swagger.host:}")
+    private String host;
+
+    @Value("${swagger.title:鎺ュ彛鏂囨。}")
+    private String title;
+
+    @Value("${swagger.description:}")
+    private String description;
+
+    @Value("${project.version:}")
+    private String version;
+
+    @Bean
+    public ApiInfo getApiInfo() {
+        return new ApiInfoBuilder()
+                .title(title)
+                .description(description)
+                .version(version)
+                .build();
+    }
+    @Bean
+    public Docket getDocket() {
+        return new Docket(DocumentationType.SWAGGER_2)
+                .apiInfo(this.getApiInfo()).groupName("銆愭帴鍙PI銆�")
+                .host(host)
+                .select()
+                .apis( basePackage("com.doumee.api.system;com.doumee.api.business;"))
+                // 璁剧疆闇�瑕佽鎵弿鐨勭被锛岃繖閲岃缃负娣诲姞浜咢Api娉ㄨВ鐨勭被
+//                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
+                .paths(PathSelectors.any())
+                .build();
+    }
+
+    /**
+     * 閲嶅啓basePackage鏂规硶锛屼娇鑳藉瀹炵幇澶氬寘璁块棶锛屽鍒惰创涓婂幓
+     * @author  teavamc
+     * @date 2019/1/26
+     * @return com.google.common.base.Predicate<springfox.documentation.RequestHandler>
+     */
+    public static Predicate<RequestHandler> basePackage(String basePackage) {
+        return input -> declaringClass(input).transform(handlerPackage(basePackage)).or(true);
+    }
+
+    private static Function<Class<?>, Boolean> handlerPackage(String basePackage)     {
+        return input -> {
+            // 寰幆鍒ゆ柇鍖归厤
+            for (String strPackage : basePackage.split(";")) {
+                boolean isMatch = input.getPackage().getName().startsWith(strPackage);
+                if (isMatch) {
+                    return true;
+                }
+            }
+            return false;
+        };
+    }
+
+    private static Optional<? extends Class<?>> declaringClass(RequestHandler input) {
+        return Optional.fromNullable(input.declaringClass());
+    }
+}
diff --git a/server/zhubo/src/main/java/com/doumee/config/swagger/SwaggerInterceptor.java b/server/zhubo/src/main/java/com/doumee/config/swagger/SwaggerInterceptor.java
new file mode 100644
index 0000000..8fd55c6
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/config/swagger/SwaggerInterceptor.java
@@ -0,0 +1,45 @@
+package com.doumee.config.swagger;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * Swagger鎷︽埅鍣�
+ * @author Eva.Caesar Liu
+ * @date 2022/04/18 18:12
+ */
+@Slf4j
+@Component
+public class SwaggerInterceptor implements HandlerInterceptor {
+
+    @Value("${swagger.enabled:false}")
+    private Boolean enabledSwagger;
+
+    @Value("${swagger.redirect-uri:/}")
+    private String redirectUri;
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
+        if (!enabledSwagger) {
+            String uri = request.getContextPath();
+            if (StringUtils.isNotBlank(redirectUri))
+                uri = request.getContextPath() + redirectUri;
+            if (StringUtils.isBlank(uri))
+                uri = "/";
+            try {
+                response.sendRedirect(uri);
+            } catch (IOException e) {
+                log.error(String.format("Redirect to '%s' for swagger throw an exception : %s", uri, e.getMessage()), e);
+            }
+            return Boolean.FALSE;
+        }
+        return Boolean.TRUE;
+    }
+}
diff --git a/server/zhubo/src/main/java/com/doumee/config/swagger/SwaggerInterceptorConfig.java b/server/zhubo/src/main/java/com/doumee/config/swagger/SwaggerInterceptorConfig.java
new file mode 100644
index 0000000..ca3aa45
--- /dev/null
+++ b/server/zhubo/src/main/java/com/doumee/config/swagger/SwaggerInterceptorConfig.java
@@ -0,0 +1,22 @@
+package com.doumee.config.swagger;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * Swagger鎷︽埅鍣ㄩ厤缃�
+ * @author Eva.Caesar Liu
+ * @date 2022/04/18 18:12
+ */
+@Configuration
+public class SwaggerInterceptorConfig implements WebMvcConfigurer {
+
+    @Autowired
+    private SwaggerInterceptor swaggerInterceptor;
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        registry.addInterceptor(swaggerInterceptor).addPathPatterns("/swagger-ui.html", "/doc.html");
+    }
+}
diff --git a/server/zhubo/src/main/resources/application.yml b/server/zhubo/src/main/resources/application.yml
new file mode 100644
index 0000000..4fb560e
--- /dev/null
+++ b/server/zhubo/src/main/resources/application.yml
@@ -0,0 +1,64 @@
+# 椤圭洰淇℃伅閰嶇疆
+project:
+  name: 棰勯�夋竻鍗曟煡璇�
+  version: 1.0.0
+  env: development
+#  env: production
+server:
+  port: 10024
+
+spring:
+#  application:
+#    name: doumeemes
+  profiles:
+    active: pro
+
+  # JSON杩斿洖閰嶇疆
+  jackson:
+    # 榛樿鏃跺尯
+    time-zone: GMT+8
+    # 榛樿鏃ユ湡鏍煎紡鍖�
+    date-format: yyyy-MM-dd HH:mm:ss
+  servlet:
+    multipart:
+      max-file-size: 200MB
+      max-request-size: 200MB
+      enabled: true
+# MyBatis閰嶇疆
+mybatis-plus:
+  mapper-locations: classpath*:/mappers/**/*.xml
+  configuration:
+    map-underscore-to-camel-case: true
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+
+# 缂撳瓨鍐呭璁剧疆
+cache:
+  session:
+    # 浼氳瘽杩囨湡鏃堕暱(s)
+    expire: 18000
+  captcha:
+    # 楠岃瘉鐮佽繃鏈熸椂闀�(s)
+    expire: 300
+
+# 璺熻釜鏃ュ織
+trace:
+  # 寮�鍚櫤鑳借窡韪ā寮�
+  smart: true
+  # 鎺掗櫎璺熻釜鐨刄RL姝e垯
+  exclude-patterns: .+/list[a-zA-Z0-9\-\_]*$, .+/tree[a-zA-Z0-9\-\_]*$, .+/page[a-zA-Z0-9\-\_]*$, .+/all[a-zA-Z0-9\-\_]*$, /swagger-resources.*
+
+# 鏃ュ織閰嶇疆
+logback:
+  level: INFO
+  appender: ${project.env}
+# dao灞傜殑鏃ュ織璁剧疆涓篸ebug锛屾柟渚挎煡鐪媠ql
+logging:
+  level:
+    doumeemes.dao: debug
+
+knife4j:
+  enable: true
+  basic:
+    enable: true
+    username: admin
+    password: 111111
\ No newline at end of file

--
Gitblit v1.9.3