Browse Source

feat(server): token访问授权

Go 4 years ago
parent
commit
3116aff653

+ 2 - 1
deploy/ssh/business.ini

@@ -1 +1,2 @@
-GROUP=/business
+GROUP=/business
+ENV=dev

+ 8 - 2
server/build.gradle

@@ -49,17 +49,22 @@ subprojects {
         parentClasspath {}
     }
 
-// 清除现有的lib目录
+    // 清除现有的lib目录
     task clearJar(type: Delete) {
         delete "$buildDir/libs/lib"
     }
 
-// 将依赖包复制到lib目录
+    // 将依赖包复制到lib目录
     task copyJar(type: Copy, dependsOn: 'clearJar') {
         from configurations.compileClasspath
         into "$buildDir/libs/lib"
     }
 
+    // 删除多余依赖
+    task clearCom(type: Copy, dependsOn: 'copyJar') {
+        delete "$buildDir/libs/lib/com"
+    }
+
     dependencies {
         compileClasspath("org.springframework.boot:spring-boot-starter")
         compileClasspath("org.springframework.boot:spring-boot-starter-web")
@@ -91,6 +96,7 @@ subprojects {
 
 //自定义环境 start
     def env = System.getProperty("ENV") ?: (System.getenv("ENV") ?: "dev")
+    println(env)
     sourceSets {
         main {
             resources {

+ 1 - 6
server/gateway-api/src/main/java/com/qxgmat/controller/api/AuthController.java

@@ -60,12 +60,7 @@ public class AuthController {
                 throw new AuthException("未登录");
             }
         }else{
-            // 默认测试token
-            if (token.equals("1234567890")){
-                user = usersService.get(1);
-            }else{
-                user = usersService.getUserByToken(token);
-            }
+            user = usersService.getUserByToken(token);
             // 用该token登录
             shiroHelp.getSession().login(shiroHelp.user(user.getMobile(), ""));
         }

+ 2 - 2
server/gateway-api/src/main/java/com/qxgmat/controller/api/MyController.java

@@ -42,8 +42,8 @@ import java.util.*;
  * Created by GaoJie on 2017/10/31.
  */
 @RestController
-@RequestMapping("/api/auth")
-@Api(tags = "登录用户接口", description = "获取与操作当前用户信息", produces = MediaType.APPLICATION_JSON_VALUE)
+@RequestMapping("/api/my")
+@Api(tags = "用户接口", description = "获取与操作当前用户信息", produces = MediaType.APPLICATION_JSON_VALUE)
 public class MyController {
 
     @Value("${upload.local_path}")

+ 11 - 6
server/gateway-api/src/main/java/com/qxgmat/service/UsersService.java

@@ -84,13 +84,18 @@ public class UsersService extends AbstractService {
      * @return
      */
     public User getUserByToken(String token){
-        String info = CipherHelp.decrypt(token, CipherHelp.DES, secret);
-        UserToken ut = tokenHandler.toObject(info);
-        Date expire = ut.getExpire();
-        if (expire.before(new Date())){
-            throw new AuthException("token错误");
+        // 默认测试token
+        if (token.equals("1234567890")){
+            return get(1);
+        }else{
+            String info = CipherHelp.decrypt(token, CipherHelp.DES, secret);
+            UserToken ut = tokenHandler.toObject(info);
+            Date expire = ut.getExpire();
+            if (expire.before(new Date())){
+                throw new AuthException("token错误");
+            }
+            return get(ut.getId());
         }
-        return get(ut.getId());
     }
 
     /**

+ 27 - 12
server/gateway-api/src/main/java/com/qxgmat/util/shiro/ShiroConfig.java

@@ -1,18 +1,15 @@
 package com.qxgmat.util.shiro;
 
-import com.nuliji.tools.shiro.DevelopFilter;
-import com.nuliji.tools.shiro.DevelopRealm;
-import com.nuliji.tools.shiro.RealmAuthenticator;
-import com.nuliji.tools.shiro.RoleFilter;
+import com.nuliji.tools.shiro.*;
 import com.nuliji.tools.shiro.cache.RedisManager;
 import com.nuliji.tools.shiro.cache.CustomCacheManager;
 import com.nuliji.tools.shiro.cache.RedisCacheProvider;
+import com.nuliji.tools.shiro.inter.HeaderTokenManager;
 import com.nuliji.tools.shiro.session.CustomSessionDao;
 import com.nuliji.tools.shiro.session.RedisSessionRepository;
 import com.nuliji.tools.shiro.session.SessionRepository;
+import com.qxgmat.util.shiro.impl.UserTokenManager;
 import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
-import org.apache.shiro.authc.credential.PasswordMatcher;
-import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
 import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
 import org.apache.shiro.cache.CacheManager;
 import org.apache.shiro.codec.Base64;
@@ -54,14 +51,15 @@ public class ShiroConfig {
         DefaultShiroFilterChainDefinition chain = new DefaultShiroFilterChainDefinition();
         chain.addPathDefinition("/admin/auth/**", "anon");
         chain.addPathDefinition("/admin/**", "role[manager]");
-        chain.addPathDefinition("/api/my/**", "role[user]");
-        chain.addPathDefinition("/api/question/**", "role[user]");
+        chain.addPathDefinition("/api/auth/**", "anon");
+        chain.addPathDefinition("/api/my/**", "token,role[user]");
+        chain.addPathDefinition("/api/question/**", "token,role[user]");
 
         chain.addPathDefinition("/**", "anon");
         return chain;
     }
 
-    @Bean
+    @Bean(name = "shiroFilter")
     public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
 
         ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
@@ -71,8 +69,10 @@ public class ShiroConfig {
 
         DevelopFilter developFilter = new DevelopFilter();
         RoleFilter roleFilter = new RoleFilter();
+        TokenFilter tokenFilter = new TokenFilter(headerTokenManager());
         filters.put("role", roleFilter);
         filters.put("develop", developFilter);
+        filters.put("token", tokenFilter);
         shiroFilterFactoryBean.setFilters(filters);
         shiroFilterFactoryBean.setFilterChainDefinitionMap(shiroFilterChainDefinition().getFilterChainMap());
         return shiroFilterFactoryBean;
@@ -122,18 +122,32 @@ public class ShiroConfig {
     }
 
     @Bean
+    public HeaderTokenManager headerTokenManager() {
+        UserTokenManager userTokenManager = new UserTokenManager();
+        return userTokenManager;
+    }
+
+    @Bean
     public UserRealm userRealm() {
         UserRealm userRealm = new UserRealm();
 //        userRealm.setCredentialsMatcher(new SimpleCredentialsMatcher());
-        userRealm.setCachingEnabled(false);
+        userRealm.setCachingEnabled(true);
         return userRealm;
     }
 
     @Bean
+    public TokenRealm tokenRealm() {
+        TokenRealm tokenRealm = new TokenRealm();
+//        userRealm.setCredentialsMatcher(new SimpleCredentialsMatcher());
+        tokenRealm.setCachingEnabled(true);
+        return tokenRealm;
+    }
+
+    @Bean
     public ManagerRealm managerRealm() {
         ManagerRealm managerRealm = new ManagerRealm();
 //        managerRealm.setCredentialsMatcher(new SimpleCredentialsMatcher());
-        managerRealm.setCachingEnabled(false);
+        managerRealm.setCachingEnabled(true);
         return managerRealm;
     }
 
@@ -147,7 +161,7 @@ public class ShiroConfig {
     @Bean
     public DevelopRealm developRealm(){
         DevelopRealm developRealm = new DevelopRealm();
-        developRealm.setCachingEnabled(false);
+        developRealm.setCachingEnabled(true);
         return developRealm;
     }
 
@@ -155,6 +169,7 @@ public class ShiroConfig {
     public Collection<Realm> realms() {
         Collection<Realm> realms = new ArrayList<>();
         realms.add(userRealm());
+        realms.add(tokenRealm());
         realms.add(oauthRealm());
         realms.add(managerRealm());
         realms.add(developRealm());

+ 65 - 0
server/gateway-api/src/main/java/com/qxgmat/util/shiro/TokenRealm.java

@@ -0,0 +1,65 @@
+package com.qxgmat.util.shiro;
+
+import com.nuliji.tools.shiro.inter.RealmAuthenticationToken;
+import com.qxgmat.data.dao.entity.User;
+import com.qxgmat.service.UsersService;
+import org.apache.commons.lang.time.FastDateFormat;
+import org.apache.shiro.authc.*;
+import org.apache.shiro.authc.credential.CredentialsMatcher;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.authz.SimpleAuthorizationInfo;
+import org.apache.shiro.cache.CacheManager;
+import org.apache.shiro.realm.AuthorizingRealm;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.ArrayList;
+import java.util.Objects;
+
+/**
+ * Created by GaoJie on 2017/11/3.
+ */
+public class TokenRealm extends AuthorizingRealm {
+    private static final FastDateFormat dateFormat = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");
+    private static final Logger logger = LoggerFactory.getLogger(TokenRealm.class);
+
+    @Autowired
+    private UsersService usersService;
+
+    public TokenRealm() {
+        super();
+        setAuthenticationTokenClass(AuthenticationToken.class);
+    }
+
+    @Override
+    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
+        String className = TokenRealm.class.getName();
+        boolean selected = false;
+        for(String realmNames: principalCollection.getRealmNames()){
+            if(realmNames.contains(className)) selected = true;
+        }
+        if(!selected) return null;
+        ArrayList<String> roleAuthorization = new ArrayList<String>();
+        SimpleAuthorizationInfo sa = new SimpleAuthorizationInfo();
+        roleAuthorization.add("user");
+        sa.addRoles(roleAuthorization);
+        return sa;
+    }
+
+    @Override
+    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
+        AuthenticationToken token = (AuthenticationToken) authenticationToken;
+        String username = (String)token.getCredentials();
+        logger.info("Login token: "+username);
+
+        User user = usersService.getUserByToken(username);
+        if (user == null || user.getId() <= 0) {
+            throw new UnknownAccountException("用户不存在!");
+        }
+        return new SimpleAuthenticationInfo(user, username, getName());
+    }
+    protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException {
+    }
+}

+ 17 - 0
server/gateway-api/src/main/java/com/qxgmat/util/shiro/impl/UserTokenManager.java

@@ -0,0 +1,17 @@
+package com.qxgmat.util.shiro.impl;
+
+import com.nuliji.tools.shiro.inter.HeaderTokenManager;
+import com.nuliji.tools.shiro.inter.impl.RealmHeaderToken;
+import com.qxgmat.util.shiro.TokenRealm;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class UserTokenManager implements HeaderTokenManager {
+
+    private static final Logger logger = LoggerFactory.getLogger(UserTokenManager.class);
+
+    @Override
+    public RealmHeaderToken getToken(String token) {
+        return new RealmHeaderToken(token, TokenRealm.class);
+    }
+}

+ 79 - 0
server/tools/src/main/java/com/nuliji/tools/shiro/TokenFilter.java

@@ -0,0 +1,79 @@
+package com.nuliji.tools.shiro;
+
+import com.alibaba.fastjson.JSON;
+import com.nuliji.tools.Response;
+import com.nuliji.tools.shiro.inter.HeaderTokenManager;
+import com.nuliji.tools.shiro.inter.impl.RealmHeaderToken;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+
+/**
+ * Created by GaoJie on 2017/11/3.
+ */
+public class TokenFilter extends BasicHttpAuthenticationFilter {
+
+    private static final Logger logger = LoggerFactory.getLogger(TokenFilter.class);
+
+    @Autowired
+    private HeaderTokenManager tokenManager;
+
+    public TokenFilter(HeaderTokenManager tokenManager) {
+        this.tokenManager = tokenManager;
+    }
+
+    @Override
+    protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
+        logger.debug("tokenFilter: {}", ((HttpServletRequest)request).getRequestURI());
+        HttpServletRequest req = (HttpServletRequest) request;
+        return req.getHeader("token") != null;
+    }
+
+//    @Override
+//    public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
+//        HttpServletRequest req = (HttpServletRequest) request;
+//        String token = req.getHeader("token");
+//        if (token == null || token.isEmpty()) {
+//            return false;
+//        }
+//        return true;
+//    }
+
+    @Override
+    protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
+        HttpServletRequest req = (HttpServletRequest) request;
+        String token = req.getHeader("token");
+        // 获取无状态Token
+        RealmHeaderToken realmHeaderToken = tokenManager.getToken(token);
+        return realmHeaderToken;
+    }
+    @Override
+    protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e,
+                                     ServletRequest request, ServletResponse response) {
+        logger.error(e.getMessage());
+        return false;
+    }
+
+    @Override
+    protected boolean sendChallenge(ServletRequest request, ServletResponse response) {
+        saveRequest(request);
+        response.setContentType(MediaType.APPLICATION_JSON_VALUE); //设置ContentType
+        response.setCharacterEncoding("UTF-8"); //避免乱码
+        try {
+            response.getWriter().write(JSON.toJSONString( new Response(101, "未授权访问", null)));
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+        }
+        return false;
+    }
+}

+ 0 - 1
server/tools/src/main/java/com/nuliji/tools/shiro/cache/CacheProvider.java

@@ -7,5 +7,4 @@ import org.apache.shiro.cache.Cache;
  */
 public interface CacheProvider {
     <k, v> Cache<k, v> getCache(String name);
-    void destroy();
 }

+ 5 - 5
server/tools/src/main/java/com/nuliji/tools/shiro/cache/CustomCacheManager.java

@@ -7,7 +7,7 @@ import org.apache.shiro.util.Destroyable;
 /**
  * Created by gaojie on 2017/11/7.
  */
-public class CustomCacheManager implements org.apache.shiro.cache.CacheManager, Destroyable {
+public class CustomCacheManager implements org.apache.shiro.cache.CacheManager {
     private CacheProvider cacheProvider;
     public CacheProvider getCacheProvider() {
         return cacheProvider;
@@ -15,10 +15,10 @@ public class CustomCacheManager implements org.apache.shiro.cache.CacheManager,
     public void setCacheProvider(CacheProvider cacheProvider) {
         this.cacheProvider = cacheProvider;
     }
-    @Override
-    public void destroy() throws Exception {
-        getCacheProvider().destroy();
-    }
+//    @Override
+//    public void destroy() throws Exception {
+//        getCacheProvider().destroy();
+//    }
     @Override
     public <k, v> Cache<k, v> getCache(String name) throws CacheException {
         return getCacheProvider().getCache(name);

+ 0 - 4
server/tools/src/main/java/com/nuliji/tools/shiro/cache/RedisCacheProvider.java

@@ -25,10 +25,6 @@ public class RedisCacheProvider implements CacheProvider {
         }
         return c;
     }
-    @Override
-    public void destroy() {
-        redisManager.flushDb();
-    }
     public RedisManager getRedisManager() {
         return redisManager;
     }

+ 2 - 2
server/tools/src/main/java/com/nuliji/tools/shiro/cache/RedisManager.java

@@ -95,8 +95,8 @@ public class RedisManager {
         RedisConnection redis = factory.getConnection();
         try {
             if(!redis.isClosed()){
-//                logger.debug("flushDb redis");
-//                redis.flushDb();
+                logger.debug("flushDb redis");
+                redis.flushDb();
             }
         } finally {
             redis.close();

+ 10 - 0
server/tools/src/main/java/com/nuliji/tools/shiro/inter/HeaderTokenManager.java

@@ -0,0 +1,10 @@
+package com.nuliji.tools.shiro.inter;
+
+import com.nuliji.tools.shiro.inter.impl.RealmHeaderToken;
+
+/**
+ * Created by GaoJie on 2017/11/3.
+ */
+public interface HeaderTokenManager {
+    RealmHeaderToken getToken(String token);
+}

+ 37 - 0
server/tools/src/main/java/com/nuliji/tools/shiro/inter/impl/RealmHeaderToken.java

@@ -0,0 +1,37 @@
+package com.nuliji.tools.shiro.inter.impl;
+
+import com.nuliji.tools.shiro.inter.RealmAuthenticationToken;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Created by GaoJie on 2017/11/3.
+ * 带Realm的登录
+ */
+public class RealmHeaderToken implements RealmAuthenticationToken, AuthenticationToken {
+
+    private static final Logger logger = LoggerFactory.getLogger(RealmHeaderToken.class);
+    protected Class realmCls;
+    private String token;
+    @Override
+    public Class getRealm() {
+        return realmCls;
+    }
+
+    public RealmHeaderToken(String token, Class realmCls){
+        this.token = token;
+        this.realmCls = realmCls;
+    }
+
+    @Override
+    public Object getPrincipal() {
+        return this.token;
+    }
+
+    @Override
+    public Object getCredentials() {
+        return this.token;
+    }
+}