diff --git a/.gitignore b/.gitignore
index 7834e46..a38c95c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,8 +10,7 @@ target/
 *.iws
 *.iml
 *.ipr
-#.idea/workspace.xml
-.idea/compiler.xml
+
 
 
 ### NetBeans ###
diff --git a/huaheng.iml b/huaheng.iml
index 5f40adb..675dfb1 100644
--- a/huaheng.iml
+++ b/huaheng.iml
@@ -195,9 +195,27 @@
     <orderEntry type="library" name="Maven: org.unbescape:unbescape:1.1.6.RELEASE" level="project" />
     <orderEntry type="library" name="Maven: org.thymeleaf.extras:thymeleaf-extras-java8time:3.0.3.RELEASE" level="project" />
     <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-devtools:2.1.3.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-data-redis:2.1.3.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.data:spring-data-redis:2.1.5.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.data:spring-data-keyvalue:2.1.5.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.data:spring-data-commons:2.1.5.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-tx:5.1.5.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-oxm:5.1.5.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: io.lettuce:lettuce-core:5.1.4.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-common:4.1.33.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-handler:4.1.33.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-buffer:4.1.33.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-codec:4.1.33.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-transport:4.1.33.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-resolver:4.1.33.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.projectreactor:reactor-core:3.2.6.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.reactivestreams:reactive-streams:1.0.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.commons:commons-pool2:2.6.1" level="project" />
     <orderEntry type="library" name="Maven: net.sourceforge.nekohtml:nekohtml:1.9.22" level="project" />
     <orderEntry type="library" name="Maven: xerces:xercesImpl:2.11.0" level="project" />
     <orderEntry type="library" name="Maven: xml-apis:xml-apis:1.4.01" level="project" />
+    <orderEntry type="library" name="Maven: io.jsonwebtoken:jjwt:0.9.1" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.9.8" level="project" />
     <orderEntry type="library" name="Maven: mysql:mysql-connector-java:8.0.16" level="project" />
     <orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper-spring-boot-starter:1.2.12" level="project" />
     <orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-starter:2.0.1" level="project" />
@@ -272,7 +290,6 @@
     <orderEntry type="library" name="Maven: org.codehaus.castor:castor-core:1.4.1" level="project" />
     <orderEntry type="library" name="Maven: javax.inject:javax.inject:1" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.9.8" level="project" />
-    <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.9.8" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.9.0" level="project" />
     <orderEntry type="library" name="Maven: net.sf.jasperreports:jasperreports-fonts:6.10.0" level="project" />
     <orderEntry type="library" name="Maven: com.itextpdf:itextpdf:5.5.7" level="project" />
@@ -295,7 +312,6 @@
     <orderEntry type="library" name="Maven: org.springframework.amqp:spring-amqp:2.1.4.RELEASE" level="project" />
     <orderEntry type="library" name="Maven: org.springframework.retry:spring-retry:1.2.4.RELEASE" level="project" />
     <orderEntry type="library" name="Maven: com.rabbitmq:amqp-client:5.4.3" level="project" />
-    <orderEntry type="library" name="Maven: org.springframework:spring-tx:5.1.5.RELEASE" level="project" />
     <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-boot-starter:3.1.2" level="project" />
     <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus:3.1.2" level="project" />
     <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-extension:3.1.2" level="project" />
diff --git a/pom.xml b/pom.xml
index 13ac078..f558341 100644
--- a/pom.xml
+++ b/pom.xml
@@ -91,12 +91,30 @@
 			<optional>true</optional> <!-- 表示依赖不会传递 -->
 		</dependency>
 
+		<!-- redis 缓存操作 -->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-data-redis</artifactId>
+		</dependency>
+
+		<!-- pool 对象池 -->
+		<dependency>
+			<groupId>org.apache.commons</groupId>
+			<artifactId>commons-pool2</artifactId>
+		</dependency>
+
 		<!-- thymeleaf网页解析 -->
 		<dependency>
 			<groupId>net.sourceforge.nekohtml</groupId>
 			<artifactId>nekohtml</artifactId>
 		</dependency>
 
+		<dependency>
+			<groupId>io.jsonwebtoken</groupId>
+			<artifactId>jjwt</artifactId>
+			<version>0.9.1</version>
+		</dependency>
+
 		<!-- Mysql8驱动包 -->
 		<dependency>
 			<groupId>mysql</groupId>
diff --git a/src/main/java/com/huaheng/framework/config/ShiroConfig.java b/src/main/java/com/huaheng/framework/config/ShiroConfig.java
index 54d6455..6878aa9 100644
--- a/src/main/java/com/huaheng/framework/config/ShiroConfig.java
+++ b/src/main/java/com/huaheng/framework/config/ShiroConfig.java
@@ -3,6 +3,7 @@ package com.huaheng.framework.config;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import javax.servlet.Filter;
+
 import org.apache.shiro.cache.ehcache.EhCacheManager;
 import org.apache.shiro.codec.Base64;
 import org.apache.shiro.mgt.SecurityManager;
@@ -28,12 +29,11 @@ import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
 
 /**
  * 权限配置加载
- * 
+ *
  * @author huaheng
  */
 @Configuration
-public class ShiroConfig
-{
+public class ShiroConfig {
     public static final String PREMISSION_STRING = "perms[\"{0}\"]";
 
     // Session超时时间,单位为毫秒(默认30分钟)
@@ -84,17 +84,13 @@ public class ShiroConfig
      * 缓存管理器 使用Ehcache实现
      */
     @Bean
-    public EhCacheManager getEhCacheManager()
-    {
+    public EhCacheManager getEhCacheManager() {
         net.sf.ehcache.CacheManager cacheManager = net.sf.ehcache.CacheManager.getCacheManager("huaheng");
         EhCacheManager em = new EhCacheManager();
-        if (StringUtils.isNull(cacheManager))
-        {
+        if (StringUtils.isNull(cacheManager)) {
             em.setCacheManagerConfigFile("classpath:ehcache/ehcache-shiro.xml");
             return em;
-        }
-        else
-        {
+        } else {
             em.setCacheManager(cacheManager);
             return em;
         }
@@ -104,8 +100,7 @@ public class ShiroConfig
      * 自定义Realm
      */
     @Bean
-    public UserRealm userRealm(EhCacheManager cacheManager)
-    {
+    public UserRealm userRealm(EhCacheManager cacheManager) {
         UserRealm userRealm = new UserRealm();
         userRealm.setCacheManager(cacheManager);
         return userRealm;
@@ -115,8 +110,7 @@ public class ShiroConfig
      * 自定义sessionDAO会话
      */
     @Bean
-    public OnlineSessionDAO sessionDAO()
-    {
+    public OnlineSessionDAO sessionDAO() {
         OnlineSessionDAO sessionDAO = new OnlineSessionDAO();
         return sessionDAO;
     }
@@ -125,8 +119,7 @@ public class ShiroConfig
      * 自定义sessionFactory会话
      */
     @Bean
-    public OnlineSessionFactory sessionFactory()
-    {
+    public OnlineSessionFactory sessionFactory() {
         OnlineSessionFactory sessionFactory = new OnlineSessionFactory();
         return sessionFactory;
     }
@@ -135,8 +128,7 @@ public class ShiroConfig
      * 自定义sessionFactory调度器
      */
     @Bean
-    public SpringSessionValidationScheduler sessionValidationScheduler()
-    {
+    public SpringSessionValidationScheduler sessionValidationScheduler() {
         SpringSessionValidationScheduler sessionValidationScheduler = new SpringSessionValidationScheduler();
         // 相隔多久检查一次session的有效性,单位毫秒,默认就是10分钟
         sessionValidationScheduler.setSessionValidationInterval(validationInterval * 60 * 1000);
@@ -149,8 +141,7 @@ public class ShiroConfig
      * 会话管理器
      */
     @Bean
-    public OnlineWebSessionManager sessionValidationManager()
-    {
+    public OnlineWebSessionManager sessionValidationManager() {
         OnlineWebSessionManager manager = new OnlineWebSessionManager();
         // 加入缓存管理器
         manager.setCacheManager(getEhCacheManager());
@@ -173,8 +164,7 @@ public class ShiroConfig
      * 会话管理器
      */
     @Bean
-    public OnlineWebSessionManager sessionManager()
-    {
+    public OnlineWebSessionManager sessionManager() {
         OnlineWebSessionManager manager = new OnlineWebSessionManager();
         // 加入缓存管理器
         manager.setCacheManager(getEhCacheManager());
@@ -199,8 +189,7 @@ public class ShiroConfig
      * 安全管理器
      */
     @Bean
-    public SecurityManager securityManager(UserRealm userRealm)
-    {
+    public SecurityManager securityManager(UserRealm userRealm) {
         DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
         // 设置realm.
         securityManager.setRealm(userRealm);
@@ -216,15 +205,13 @@ public class ShiroConfig
     /**
      * 退出过滤器
      */
-    public LogoutFilter logoutFilter()
-    {
+    public LogoutFilter logoutFilter() {
         LogoutFilter logoutFilter = new LogoutFilter();
         logoutFilter.setLoginUrl(loginUrl);
         return logoutFilter;
     }
 
-    public LogoutFilter logoutFilters()
-    {
+    public LogoutFilter logoutFilters() {
         LogoutFilter logoutFilter = new LogoutFilter();
         logoutFilter.setLoginUrl(loginUrls);
         return logoutFilter;
@@ -234,8 +221,7 @@ public class ShiroConfig
      * Shiro过滤器配置
      */
     @Bean
-    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager)
-    {
+    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
         ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
         // Shiro的核心安全接口,这个属性是必须的
         shiroFilterFactoryBean.setSecurityManager(securityManager);
@@ -270,6 +256,7 @@ public class ShiroConfig
         filterChainDefinitionMap.put("/mobile/login", "anon");
         filterChainDefinitionMap.put("/getWarehouseByUserCode", "anon");
         filterChainDefinitionMap.put("/API/WMS/v2/login", "anon");
+        filterChainDefinitionMap.put("/api/**", "anon");
         // 系统权限列表
 //        filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());
 
@@ -292,8 +279,7 @@ public class ShiroConfig
      * 自定义在线用户处理过滤器
      */
     @Bean
-    public OnlineSessionFilter onlineSessionFilter()
-    {
+    public OnlineSessionFilter onlineSessionFilter() {
         OnlineSessionFilter onlineSessionFilter = new OnlineSessionFilter();
         onlineSessionFilter.setLoginUrl(loginUrl);
         return onlineSessionFilter;
@@ -303,8 +289,7 @@ public class ShiroConfig
      * 自定义在线用户同步过滤器
      */
     @Bean
-    public SyncOnlineSessionFilter syncOnlineSessionFilter()
-    {
+    public SyncOnlineSessionFilter syncOnlineSessionFilter() {
         SyncOnlineSessionFilter syncOnlineSessionFilter = new SyncOnlineSessionFilter();
         return syncOnlineSessionFilter;
     }
@@ -312,8 +297,7 @@ public class ShiroConfig
     /**
      * cookie 属性设置
      */
-    public SimpleCookie rememberMeCookie()
-    {
+    public SimpleCookie rememberMeCookie() {
         SimpleCookie cookie = new SimpleCookie("rememberMe");
         cookie.setDomain(domain);
         cookie.setPath(path);
@@ -325,8 +309,7 @@ public class ShiroConfig
     /**
      * 记住我
      */
-    public CookieRememberMeManager rememberMeManager()
-    {
+    public CookieRememberMeManager rememberMeManager() {
         CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
         cookieRememberMeManager.setCookie(rememberMeCookie());
         cookieRememberMeManager.setCipherKey(Base64.decode("fCq+/xW488hMTCD+cmJ3aQ=="));
@@ -337,8 +320,7 @@ public class ShiroConfig
      * thymeleaf模板引擎和shiro框架的整合
      */
     @Bean
-    public ShiroDialect shiroDialect()
-    {
+    public ShiroDialect shiroDialect() {
         return new ShiroDialect();
     }
 
@@ -347,8 +329,7 @@ public class ShiroConfig
      */
     @Bean
     public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
-            @Qualifier("securityManager") SecurityManager securityManager)
-    {
+            @Qualifier("securityManager") SecurityManager securityManager) {
         AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
         authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
         return authorizationAttributeSourceAdvisor;
diff --git a/src/main/java/com/huaheng/framework/redis/RedisCache.java b/src/main/java/com/huaheng/framework/redis/RedisCache.java
new file mode 100644
index 0000000..3699ee1
--- /dev/null
+++ b/src/main/java/com/huaheng/framework/redis/RedisCache.java
@@ -0,0 +1,180 @@
+package com.huaheng.framework.redis;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.*;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * spring redis 工具类
+ *
+ * @author ruoyi
+ **/
+@SuppressWarnings(value = {"unchecked", "rawtypes"})
+@Component
+public class RedisCache {
+
+    @Autowired
+    public RedisTemplate redisTemplate;
+
+    /**
+     * 缓存基本的对象,Integer、String、实体类等
+     *
+     * @param key   缓存的键值
+     * @param value 缓存的值
+     * @return 缓存的对象
+     */
+    public <T> ValueOperations<String, T> setCacheObject(String key, T value) {
+        ValueOperations<String, T> operation = redisTemplate.opsForValue();
+        operation.set(key, value);
+        return operation;
+    }
+
+    /**
+     * 缓存基本的对象,Integer、String、实体类等
+     *
+     * @param key      缓存的键值
+     * @param value    缓存的值
+     * @param timeout  时间
+     * @param timeUnit 时间颗粒度
+     * @return 缓存的对象
+     */
+    public <T> ValueOperations<String, T> setCacheObject(String key, T value, Integer timeout, TimeUnit timeUnit) {
+        ValueOperations<String, T> operation = redisTemplate.opsForValue();
+        operation.set(key, value, timeout, timeUnit);
+        return operation;
+    }
+
+    /**
+     * 获得缓存的基本对象。
+     *
+     * @param key 缓存键值
+     * @return 缓存键值对应的数据
+     */
+    public <T> T getCacheObject(String key) {
+        ValueOperations<String, T> operation = redisTemplate.opsForValue();
+        return operation.get(key);
+    }
+
+    /**
+     * 删除单个对象
+     *
+     * @param key
+     */
+    public void deleteObject(String key) {
+        redisTemplate.delete(key);
+    }
+
+    /**
+     * 删除集合对象
+     *
+     * @param collection
+     */
+    public void deleteObject(Collection collection) {
+        redisTemplate.delete(collection);
+    }
+
+    /**
+     * 缓存List数据
+     *
+     * @param key      缓存的键值
+     * @param dataList 待缓存的List数据
+     * @return 缓存的对象
+     */
+    public <T> ListOperations<String, T> setCacheList(String key, List<T> dataList) {
+        ListOperations listOperation = redisTemplate.opsForList();
+        if (null != dataList) {
+            int size = dataList.size();
+            for (int i = 0; i < size; i++) {
+                listOperation.leftPush(key, dataList.get(i));
+            }
+        }
+        return listOperation;
+    }
+
+    /**
+     * 获得缓存的list对象
+     *
+     * @param key 缓存的键值
+     * @return 缓存键值对应的数据
+     */
+    public <T> List<T> getCacheList(String key) {
+        List<T> dataList = new ArrayList<T>();
+        ListOperations<String, T> listOperation = redisTemplate.opsForList();
+        Long size = listOperation.size(key);
+
+        for (int i = 0; i < size; i++) {
+            dataList.add(listOperation.index(key, i));
+        }
+        return dataList;
+    }
+
+    /**
+     * 缓存Set
+     *
+     * @param key     缓存键值
+     * @param dataSet 缓存的数据
+     * @return 缓存数据的对象
+     */
+    public <T> BoundSetOperations<String, T> setCacheSet(String key, Set<T> dataSet) {
+        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
+        Iterator<T> it = dataSet.iterator();
+        while (it.hasNext()) {
+            setOperation.add(it.next());
+        }
+        return setOperation;
+    }
+
+    /**
+     * 获得缓存的set
+     *
+     * @param key
+     * @return
+     */
+    public <T> Set<T> getCacheSet(String key) {
+        Set<T> dataSet = new HashSet<T>();
+        BoundSetOperations<String, T> operation = redisTemplate.boundSetOps(key);
+        dataSet = operation.members();
+        return dataSet;
+    }
+
+    /**
+     * 缓存Map
+     *
+     * @param key
+     * @param dataMap
+     * @return
+     */
+    public <T> HashOperations<String, String, T> setCacheMap(String key, Map<String, T> dataMap) {
+        HashOperations hashOperations = redisTemplate.opsForHash();
+        if (null != dataMap) {
+            for (Map.Entry<String, T> entry : dataMap.entrySet()) {
+                hashOperations.put(key, entry.getKey(), entry.getValue());
+            }
+        }
+        return hashOperations;
+    }
+
+    /**
+     * 获得缓存的Map
+     *
+     * @param key
+     * @return
+     */
+    public <T> Map<String, T> getCacheMap(String key) {
+        Map<String, T> map = redisTemplate.opsForHash().entries(key);
+        return map;
+    }
+
+    /**
+     * 获得缓存的基本对象列表
+     *
+     * @param pattern 字符串前缀
+     * @return 对象列表
+     */
+    public Collection<String> keys(String pattern) {
+        return redisTemplate.keys(pattern);
+    }
+}
diff --git a/src/main/java/com/huaheng/framework/token/ApiInterceptor.java b/src/main/java/com/huaheng/framework/token/ApiInterceptor.java
new file mode 100644
index 0000000..13966d7
--- /dev/null
+++ b/src/main/java/com/huaheng/framework/token/ApiInterceptor.java
@@ -0,0 +1,52 @@
+package com.huaheng.framework.token;
+
+import com.alibaba.fastjson.JSONObject;
+import com.huaheng.common.utils.ServletUtils;
+import com.huaheng.common.utils.StringUtils;
+import com.huaheng.framework.redis.RedisCache;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.security.SignatureException;
+
+/**
+ * Created by Enzo Cotter on 2020/6/11.
+ */
+public class ApiInterceptor implements HandlerInterceptor {
+
+    @Resource
+    private RedisCache redisCache;
+    /**
+     * 可以在这里设置各种规则,取到token后解析,来验证token有效性,有效期等等。这里仅仅验证了是不是token为空。
+     */
+    @Override
+    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
+        //这个就是从http头中取约定好的token的key。
+        String token = httpServletRequest.getHeader("Authorization");
+        try {
+            if (token == null || token.trim().equals("")) {
+                throw new SignatureException("token is null");
+            } else {
+                token = token.substring(7);
+                String user = redisCache.getCacheObject(token);
+                if (StringUtils.isEmpty(user)) {
+                    JSONObject jsonObject = new JSONObject();
+                    jsonObject.put("msg", "token不正确或过期");
+                    jsonObject.put("code", 401);
+                    ServletUtils.renderString(httpServletResponse, jsonObject.toString());
+                    return false;
+                }
+            }
+        } catch (SignatureException e) {
+            JSONObject jsonObject = new JSONObject();
+            jsonObject.put("msg", "请求参数中找不到Token");
+            jsonObject.put("code", 401);
+            ServletUtils.renderString(httpServletResponse, jsonObject.toString());
+            return false;
+        }
+
+        return true;
+    }
+}
diff --git a/src/main/java/com/huaheng/framework/token/TokenController.java b/src/main/java/com/huaheng/framework/token/TokenController.java
new file mode 100644
index 0000000..81994dd
--- /dev/null
+++ b/src/main/java/com/huaheng/framework/token/TokenController.java
@@ -0,0 +1,56 @@
+package com.huaheng.framework.token;
+
+import com.huaheng.common.utils.StringUtils;
+import com.huaheng.framework.shiro.service.PasswordService;
+import com.huaheng.framework.web.controller.BaseController;
+import com.huaheng.framework.web.domain.Result;
+import com.huaheng.pc.system.user.domain.User;
+import com.huaheng.pc.system.user.service.IUserService;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Calendar;
+
+/**
+ * Created by Enzo Cotter on 2020/6/11.
+ */
+@RestController
+@RequestMapping("/api")
+public class TokenController extends BaseController {
+
+    @Resource
+    private TokenService tokenService;
+    @Resource
+    private IUserService userService;
+    @Resource
+    private PasswordService passwordService;
+
+    @PostMapping("/getToken")
+    @ResponseBody
+    public Result getToken(String username, String password, String warehouseCode) {
+        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
+            return Result.error("用户名和密码不能为空");
+        }
+        if (StringUtils.isEmpty(warehouseCode)) {
+            return Result.error("请选择仓库");
+        }
+        User user = userService.selectUserByLoginName(username);
+
+        if (!userService.checkWarehouseCodeAndUserName(warehouseCode, username)) {
+            return Result.error("用户没有该仓库操作权限");
+        }
+        if (user.getPassword().equals(passwordService.encryptPassword(user.getLoginName(), password, user.getSalt()))) {
+            String token = tokenService.createToken(user);
+            Result ajaxResult = Result.success("成功");
+            ajaxResult.put("token", token);
+            ajaxResult.put("expireTime", Calendar.getInstance().getTime());
+            return ajaxResult;
+        } else {
+            return Result.error("密码错误");
+        }
+
+    }
+}
diff --git a/src/main/java/com/huaheng/framework/token/TokenService.java b/src/main/java/com/huaheng/framework/token/TokenService.java
new file mode 100644
index 0000000..e28763f
--- /dev/null
+++ b/src/main/java/com/huaheng/framework/token/TokenService.java
@@ -0,0 +1,79 @@
+package com.huaheng.framework.token;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.google.gson.JsonObject;
+import com.huaheng.common.exception.service.ServiceException;
+import com.huaheng.framework.redis.RedisCache;
+import com.huaheng.pc.system.user.domain.User;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jws;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import jdk.nashorn.internal.parser.JSONParser;
+import org.springframework.boot.autoconfigure.cache.CacheProperties;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * token生成与解析
+ * @author Enzo Cotter
+ * @date 2020/6/11
+ */
+@Service
+public class TokenService {
+
+    @Resource
+    private RedisCache redisCache;
+
+    /**
+     * 有效期7天
+     */
+    private static final int EXPIRE_TIME = 7;
+
+    /**
+     * 盐
+     */
+    private static final String signingKey = "secret";
+
+    /**
+     * 创建token
+     * @param user 用户
+     * @return
+     */
+    public String createToken(User user){
+        //签发时间
+        Date iatTime = new Date();
+        //expire time
+        Calendar nowTime = Calendar.getInstance();
+        nowTime.add(Calendar.DATE, EXPIRE_TIME);
+        Date expireTime = nowTime.getTime();
+
+        Claims claims = Jwts.claims();
+        claims.put("user", user);
+        claims.setIssuedAt(iatTime);
+        String token = Jwts.builder().setClaims(claims)
+                .signWith(SignatureAlgorithm.HS512,signingKey).compact();
+        if (redisCache.setCacheObject(token, user.toString(), EXPIRE_TIME, TimeUnit.DAYS) == null) {
+            throw new ServiceException("redis异常");
+        }
+        return token;
+    }
+
+    /**
+     * 解析token
+     * @param token
+     */
+    public void parseToken(String token){
+        Jws<Claims> jws = Jwts.parser().setSigningKey(signingKey).parseClaimsJws(token);
+        Claims claims = jws.getBody();
+        Map<String,String> header = jws.getHeader();
+        System.out.println("parse");
+    }
+}
diff --git a/src/main/java/com/huaheng/framework/token/WebAppConfigurer.java b/src/main/java/com/huaheng/framework/token/WebAppConfigurer.java
new file mode 100644
index 0000000..24306c8
--- /dev/null
+++ b/src/main/java/com/huaheng/framework/token/WebAppConfigurer.java
@@ -0,0 +1,23 @@
+package com.huaheng.framework.token;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * Created by Enzo Cotter on 2020/6/11.
+ */
+@Configuration
+public class WebAppConfigurer implements WebMvcConfigurer {
+
+    @Bean
+    ApiInterceptor apiInterceptor(){return new ApiInterceptor();}
+
+    @Override
+    public void addInterceptors(InterceptorRegistry interceptorRegistry) {
+        interceptorRegistry.addInterceptor(apiInterceptor())
+                .addPathPatterns("/api/**")
+                .excludePathPatterns("/api/getToken");
+    }
+}
diff --git a/src/main/java/com/huaheng/framework/web/domain/Result.java b/src/main/java/com/huaheng/framework/web/domain/Result.java
new file mode 100644
index 0000000..597ef1e
--- /dev/null
+++ b/src/main/java/com/huaheng/framework/web/domain/Result.java
@@ -0,0 +1,142 @@
+package com.huaheng.framework.web.domain;
+
+import com.huaheng.common.utils.StringUtils;
+
+import java.util.HashMap;
+
+/**
+ *  操作消息提醒
+ * @author Enzo Cotter
+ * @date 2020/6/11
+ */
+public class Result extends HashMap<String, Object> {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 状态码
+     */
+    public static final String CODE_TAG = "code";
+
+    /**
+     * 返回内容
+     */
+    public static final String MSG_TAG = "msg";
+
+    /**
+     * 数据对象
+     */
+    public static final String DATA_TAG = "data";
+
+    /**
+     * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
+     */
+    public Result() {
+    }
+
+    /**
+     * 初始化一个新创建的 AjaxResult 对象
+     *
+     * @param code 状态码
+     * @param msg  返回内容
+     */
+    public Result(int code, String msg) {
+        super.put(CODE_TAG, code);
+        super.put(MSG_TAG, msg);
+    }
+
+    /**
+     * 初始化一个新创建的 AjaxResult 对象
+     *
+     * @param code 状态码
+     * @param msg  返回内容
+     * @param data 数据对象
+     */
+    public Result(int code, String msg, Object data) {
+        super.put(CODE_TAG, code);
+        super.put(MSG_TAG, msg);
+        if (StringUtils.isNotNull(data)) {
+            super.put(DATA_TAG, data);
+        }
+    }
+
+    /**
+     * 返回成功消息
+     *
+     * @return 成功消息
+     */
+    public static Result success() {
+        return Result.success("操作成功");
+    }
+
+    /**
+     * 返回成功数据
+     *
+     * @return 成功消息
+     */
+    public static Result success(Object data) {
+        return Result.success("操作成功", data);
+    }
+
+    /**
+     * 返回成功消息
+     *
+     * @param msg 返回内容
+     * @return 成功消息
+     */
+    public static Result success(String msg) {
+        return Result.success(msg, null);
+    }
+
+    /**
+     * 返回成功消息
+     *
+     * @param msg  返回内容
+     * @param data 数据对象
+     * @return 成功消息
+     */
+    public static Result success(String msg, Object data) {
+        return new Result(200, msg, data);
+    }
+
+    /**
+     * 返回错误消息
+     *
+     * @return
+     */
+    public static Result error() {
+        return Result.error("操作失败");
+    }
+
+    /**
+     * 返回错误消息
+     *
+     * @param msg 返回内容
+     * @return 警告消息
+     */
+    public static Result error(String msg) {
+        return Result.error(msg, null);
+    }
+
+    /**
+     * 返回错误消息
+     *
+     * @param msg  返回内容
+     * @param data 数据对象
+     * @return 警告消息
+     */
+    public static Result error(String msg, Object data) {
+        return new Result(400, msg, data);
+    }
+
+    /**
+     * 返回错误消息
+     *
+     * @param code 状态码
+     * @param msg  返回内容
+     * @return 警告消息
+     */
+    public static Result error(int code, String msg) {
+        return new Result(code, msg, null);
+    }
+
+}
diff --git a/src/main/java/com/huaheng/pc/receipt/receiving/controller/ReceivingController.java b/src/main/java/com/huaheng/pc/receipt/receiving/controller/ReceivingController.java
index e643c20..70d311d 100644
--- a/src/main/java/com/huaheng/pc/receipt/receiving/controller/ReceivingController.java
+++ b/src/main/java/com/huaheng/pc/receipt/receiving/controller/ReceivingController.java
@@ -98,7 +98,7 @@ public class ReceivingController extends BaseController {
 //        if (count > 0)  {
 //            return AjaxResult.error("仓库有“出库查看”任务没有完成,请先完成任务");
 //        }
-        AjaxResult result = receiptContainerHeaderService.saveCountain(receiptCode, containerCode, receiptDetailId,
+        AjaxResult result = receiptContainerHeaderService.saveContainer(receiptCode, containerCode, receiptDetailId,
                  locationCode, qty, locatingRule);
         return result;
     }
diff --git a/src/main/java/com/huaheng/pc/system/user/mapper/UserMapper.java b/src/main/java/com/huaheng/pc/system/user/mapper/UserMapper.java
index 3be853e..bfebcf1 100644
--- a/src/main/java/com/huaheng/pc/system/user/mapper/UserMapper.java
+++ b/src/main/java/com/huaheng/pc/system/user/mapper/UserMapper.java
@@ -119,6 +119,14 @@ public interface UserMapper
     public User checkEmailUnique(String email);
 
     /**
+     * 检查用户是否拥有该仓库权限
+     * @param warehouseCode 仓库code
+     * @param username 登录名
+     * @return
+     */
+    List<Map<String, Object>> checkWarehouseCodeAndUserName(@Param("warehouseCode") String warehouseCode, @Param("loginName") String username);
+
+    /**
      * 根据用户id查询该用户所有仓库
      * @param userId
      * @return
diff --git a/src/main/java/com/huaheng/pc/system/user/service/IUserService.java b/src/main/java/com/huaheng/pc/system/user/service/IUserService.java
index d20d89c..7dc503d 100644
--- a/src/main/java/com/huaheng/pc/system/user/service/IUserService.java
+++ b/src/main/java/com/huaheng/pc/system/user/service/IUserService.java
@@ -200,6 +200,8 @@ public interface IUserService
     public User selectmen(String loginName);
 
     public int batchUserWarehouse(@Param("userWarehouseList") List<SysUserWarehouse> userWarehouseList);
+
+    boolean checkWarehouseCodeAndUserName(String warehouseCode, String username);
 }
 
 
diff --git a/src/main/java/com/huaheng/pc/system/user/service/UserServiceImpl.java b/src/main/java/com/huaheng/pc/system/user/service/UserServiceImpl.java
index fa48246..a37842d 100644
--- a/src/main/java/com/huaheng/pc/system/user/service/UserServiceImpl.java
+++ b/src/main/java/com/huaheng/pc/system/user/service/UserServiceImpl.java
@@ -594,4 +594,9 @@ public class UserServiceImpl implements IUserService
         return sysUserWarehouseMapper.batchUserWarehouse(userWarehouseList);
     }
 
+    @Override
+    public boolean checkWarehouseCodeAndUserName(String warehouseCode, String username) {
+        return !userMapper.checkWarehouseCodeAndUserName(warehouseCode, username).isEmpty();
+    }
+
 }
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 913ade4..a35a52d 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -84,6 +84,26 @@ spring:
     password: owobzjvlgsxrbdfe
     # 编码类型
     default-encoding: utf-8
+  # redis 配置
+  redis:
+    # 地址
+    host: localhost
+    # 端口,默认为6379
+    port: 6379
+    # 密码
+    password:
+    # 连接超时时间
+    timeout: 10s
+    lettuce:
+      pool:
+        # 连接池中的最小空闲连接
+        min-idle: 0
+        # 连接池中的最大空闲连接
+        max-idle: 8
+        # 连接池的最大数据库连接数
+        max-active: 8
+        # #连接池最大阻塞等待时间(使用负值表示没有限制)
+        max-wait: -1ms
 
 mybatis-plus:
   mapper-locations: classpath:mybatis/**/*.xml
diff --git a/src/main/resources/mybatis/system/UserMapper.xml b/src/main/resources/mybatis/system/UserMapper.xml
index 88a4010..5646090 100644
--- a/src/main/resources/mybatis/system/UserMapper.xml
+++ b/src/main/resources/mybatis/system/UserMapper.xml
@@ -203,5 +203,12 @@
 	<update id="insertupdateTime" >
 		update sys_user set updateTime = #{date} where loginName = #{cPersonCode}
 	</update>
+	<select id="checkWarehouseCodeAndUserName" resultType="java.util.Map">
+	    SELECT  r.`name`, r.code
+        FROM sys_user u
+			 LEFT JOIN sys_user_warehouse ur ON u.id = ur.userId
+			 LEFT JOIN warehouse r ON ur.warehouseCode = r.code
+		WHERE  u.loginName=#{loginName,jdbcType=VARCHAR} AND r.`code` =#{warehouseCode,jdbcType=VARCHAR}
+    </select>
 	
 </mapper>
\ No newline at end of file
diff --git a/src/main/resources/templates/config/container/print.html b/src/main/resources/templates/config/container/print.html
index 553327a..3c033d6 100644
--- a/src/main/resources/templates/config/container/print.html
+++ b/src/main/resources/templates/config/container/print.html
@@ -4,7 +4,7 @@
 <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
     <head th:include="include :: header"></head>
-    <title>库存交易明细</title>
+    <title>容器打印</title>
     <!--<link href="css/bootstrap.min.css" rel="stylesheet" />-->
     <!--<link href="css/font-awesome.min.css" rel="stylesheet" />-->
     <!--&lt;!&ndash;[if IE]>-->