ソースを参照

继续优化权限

zhouhao 7 年 前
コミット
b5a8cf712c
14 ファイル変更124 行追加47 行削除
  1. 17 3
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/exception/UnAuthorizedException.java
  2. 14 4
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/MemoryUserTokenManager.java
  3. 8 7
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/SimpleUserToken.java
  4. 2 1
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserToken.java
  5. 21 3
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserTokenManager.java
  6. 1 1
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/DefaultAuthorizingHandler.java
  7. 1 1
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/access/OwnCreatedDataAccessHandler.java
  8. 5 1
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/UserTokenAuthenticationSupplier.java
  9. 2 7
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/WebUserTokenInterceptor.java
  10. 4 4
      hsweb-commons/hsweb-commons-controller/src/main/java/org/hswebframework/web/controller/message/ResponseMessage.java
  11. 14 5
      hsweb-examples/hsweb-examples-simple/src/main/java/org/hswebframework/web/example/simple/SpringBootExample.java
  12. 4 4
      hsweb-starter/hsweb-spring-boot-starter/src/main/java/org/hswebframework/web/starter/RestControllerExceptionTranslator.java
  13. 3 6
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-controller/src/main/java/org/hswebframework/web/controller/authorization/AuthorizationController.java
  14. 28 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-controller/src/main/java/org/hswebframework/web/controller/authorization/UserController.java

+ 17 - 3
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/exception/UnAuthorizedException.java

@@ -18,6 +18,8 @@
 
 package org.hswebframework.web.authorization.exception;
 
+import org.hswebframework.web.authorization.token.TokenState;
+
 /**
  * 未授权异常
  *
@@ -27,15 +29,27 @@ package org.hswebframework.web.authorization.exception;
 public class UnAuthorizedException extends RuntimeException {
     private static final long serialVersionUID = 2422918455013900645L;
 
+    private TokenState state;
+
     public UnAuthorizedException() {
-        this("{un_authorization}");
+        this(TokenState.expired);
+    }
+
+    public UnAuthorizedException(TokenState state) {
+        this("{un_authorization}", state);
     }
 
-    public UnAuthorizedException(String message) {
+    public UnAuthorizedException(String message, TokenState state) {
         super(message);
+        this.state = state;
     }
 
-    public UnAuthorizedException(String message, Throwable cause) {
+    public UnAuthorizedException(String message, TokenState state, Throwable cause) {
         super(message, cause);
+        this.state = state;
+    }
+
+    public TokenState getState() {
+        return state;
     }
 }

+ 14 - 4
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/MemoryUserTokenManager.java

@@ -18,8 +18,8 @@
 
 package org.hswebframework.web.authorization.token;
 
-import org.hswebframework.web.authorization.token.event.UserSignInEvent;
 import org.hswebframework.web.authorization.listener.AuthorizationListenerDispatcher;
+import org.hswebframework.web.authorization.token.event.UserSignInEvent;
 
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
@@ -69,7 +69,6 @@ public class MemoryUserTokenManager implements UserTokenManager {
         if (null == detail) return null;
         if (System.currentTimeMillis() - detail.getLastRequestTime() > timeout * 1000) {
             detail.setState(TokenState.expired);
-            // signOutByToken(detail.getToken());
             return detail;
         }
         return detail;
@@ -97,9 +96,8 @@ public class MemoryUserTokenManager implements UserTokenManager {
 
     @Override
     public boolean tokenIsLoggedIn(String token) {
-        UserToken userToken = getByToken(token);
 
-        return userToken != null && userToken.isEffective();
+        return getByToken(token) != null;
     }
 
     @Override
@@ -141,6 +139,18 @@ public class MemoryUserTokenManager implements UserTokenManager {
         tokenUserStorage.remove(token);
     }
 
+    @Override
+    public void changeTokenState(String token, TokenState state) {
+        SimpleUserToken userToken = getByToken(token);
+        if (null != userToken)
+            userToken.setState(state);
+    }
+
+    @Override
+    public void changeUserState(String user, TokenState state) {
+        getByUserId(user).forEach(token -> changeTokenState(token.getToken(), state));
+    }
+
     @Override
     public UserToken signIn(String token, String userId) {
         SimpleUserToken detail = new SimpleUserToken(userId, token);

+ 8 - 7
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/SimpleUserToken.java

@@ -4,8 +4,9 @@ import java.util.concurrent.atomic.AtomicLong;
 
 /**
  * 用户令牌信息
- * @since 3.0
+ *
  * @author zhouhao
+ * @since 3.0
  */
 public class SimpleUserToken implements UserToken {
 
@@ -13,13 +14,13 @@ public class SimpleUserToken implements UserToken {
 
     private String token;
 
-    private TokenState state;
+    private volatile TokenState state;
 
-    private AtomicLong requestTimesCounter=new AtomicLong(0);
+    private AtomicLong requestTimesCounter = new AtomicLong(0);
 
-    private volatile long lastRequestTime=System.currentTimeMillis();
+    private volatile long lastRequestTime = System.currentTimeMillis();
 
-    private volatile long firstRequestTime=System.currentTimeMillis();
+    private volatile long firstRequestTime = System.currentTimeMillis();
 
     private volatile long requestTimes;
 
@@ -86,8 +87,8 @@ public class SimpleUserToken implements UserToken {
         requestTimesCounter.set(requestTimes);
     }
 
-    void touch(){
+    void touch() {
         requestTimesCounter.addAndGet(1);
-        lastRequestTime=System.currentTimeMillis();
+        lastRequestTime = System.currentTimeMillis();
     }
 }

+ 2 - 1
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserToken.java

@@ -65,10 +65,11 @@ public interface UserToken extends Serializable, Comparable<UserToken> {
         return getState() == TokenState.offline;
     }
 
-    default void validate() {
+    default boolean validate() {
         if (!isEffective()) {
             throw new UnAuthorizedException(getState());
         }
+        return true;
     }
 
     @Override

+ 21 - 3
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserTokenManager.java

@@ -38,6 +38,7 @@ public interface UserTokenManager {
 
     /**
      * 根据用户id,获取全部令牌信息,如果设置了不能跨地点登陆,返回值只可能是{@code null}或者size为1的list
+     *
      * @param userId 用户id
      * @return 授权信息
      */
@@ -50,7 +51,6 @@ public interface UserTokenManager {
     boolean userIsLoggedIn(String userId);
 
     /**
-     *
      * @param token token
      * @return token是否已登记
      */
@@ -62,7 +62,6 @@ public interface UserTokenManager {
     long totalUser();
 
     /**
-     *
      * @return 总token数量
      */
     long totalToken();
@@ -81,19 +80,38 @@ public interface UserTokenManager {
 
     /**
      * 根据token删除
+     *
      * @param token
      */
     void signOutByToken(String token);
 
     /**
-     * 登记一个用户的token
+     * 修改userId的状态
+     *
+     * @param userId userId
+     * @param state  状态
+     */
+    void changeUserState(String userId, TokenState state);
+
+    /**
+     * 修改token的状态
+     *
      * @param token token
+     * @param state 状态
+     */
+    void changeTokenState(String token, TokenState state);
+
+    /**
+     * 登记一个用户的token
+     *
+     * @param token  token
      * @param userId 用户id
      */
     UserToken signIn(String token, String userId);
 
     /**
      * 更新token,使其不过期
+     *
      * @param token token
      */
     void touch(String token);

+ 1 - 1
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/DefaultAuthorizingHandler.java

@@ -57,7 +57,7 @@ public class DefaultAuthorizingHandler implements AuthorizingHandler {
 
     protected void handleDataAccess(AuthorizingContext context) {
         if (dataAccessController == null) {
-            logger.warn("dataAccessController is null,skip data access control!");
+            logger.warn("dataAccessController is null,skip result access control!");
             return;
         }
         List<Permission> permission = context.getAuthentication().getPermissions()

+ 1 - 1
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/access/OwnCreatedDataAccessHandler.java

@@ -44,7 +44,7 @@ public class OwnCreatedDataAccessHandler implements DataAccessHandler {
                 case Permission.ACTION_UPDATE:
                     return doRWAccess(own, context,controller);
                 case Permission.ACTION_ADD:
-                    //put creator_id to data
+                    //put creator_id to result
                     return putCreatorId(own, context);
                 default:
                     logger.warn("action: {} not support now!", access.getAction());

+ 5 - 1
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/UserTokenAuthenticationSupplier.java

@@ -31,6 +31,10 @@ public class UserTokenAuthenticationSupplier implements AuthenticationSupplier {
 
     @Override
     public Authentication get() {
-        return ThreadLocalUtils.get(Authentication.class.getName(), () -> get(Optional.ofNullable(getCurrentUserToken()).map(UserToken::getUserId).orElse(null)));
+        return ThreadLocalUtils.get(Authentication.class.getName(), () ->
+                get(Optional.ofNullable(getCurrentUserToken())
+                        .filter(UserToken::validate) //验证token,如果不是正常状态,将会抛出异常
+                        .map(UserToken::getUserId)
+                        .orElse(null)));
     }
 }

+ 2 - 7
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/WebUserTokenInterceptor.java

@@ -1,5 +1,6 @@
 package org.hswebframework.web.authorization.basic.web;
 
+import org.hswebframework.web.authorization.exception.UnAuthorizedException;
 import org.hswebframework.web.authorization.token.UserToken;
 import org.hswebframework.web.authorization.token.UserTokenManager;
 import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
@@ -33,14 +34,8 @@ public class WebUserTokenInterceptor extends HandlerInterceptorAdapter {
         UserToken userToken = userTokenManager.getByToken(token);
         if (userToken == null) {
             return true;
-        } else if (userToken.isEffective()) {
+        } else {
             UserTokenHolder.setCurrent(userToken);
-        } else if (userToken.isExpired()) {
-            // TODO: 17-8-16 发送登录超时的错误信息
-            userTokenManager.signOutByToken(token);
-        } else if (userToken.isOffline()) {
-            // TODO: 17-8-16 发送已被踢出的错误信息
-            userTokenManager.signOutByToken(token);
         }
         return true;
     }

+ 4 - 4
hsweb-commons/hsweb-commons-controller/src/main/java/org/hswebframework/web/controller/message/ResponseMessage.java

@@ -82,9 +82,9 @@ public class ResponseMessage<T> implements Serializable {
         return this;
     }
 
-    public static <T> ResponseMessage<T> ok(T data) {
+    public static <T> ResponseMessage<T> ok(T result) {
         return new ResponseMessage<T>()
-                .data(data)
+                .result(result)
                 .putTimeStamp()
                 .status(200);
     }
@@ -94,8 +94,8 @@ public class ResponseMessage<T> implements Serializable {
 //        return this;
 //    }
 
-    public ResponseMessage<T> data(T data) {
-        this.result = data;
+    public ResponseMessage<T> result(T result) {
+        this.result = result;
         return this;
     }
 

+ 14 - 5
hsweb-examples/hsweb-examples-simple/src/main/java/org/hswebframework/web/example/simple/SpringBootExample.java

@@ -18,10 +18,12 @@
 package org.hswebframework.web.example.simple;
 
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.serializer.SerializerFeature;
 import org.hswebframework.web.authorization.Authentication;
 import org.hswebframework.web.authorization.Permission;
 import org.hswebframework.web.authorization.access.DataAccessConfig;
 import org.hswebframework.web.authorization.basic.configuration.EnableAopAuthorize;
+import org.hswebframework.web.authorization.basic.web.UserTokenHolder;
 import org.hswebframework.web.authorization.simple.SimpleFieldFilterDataAccessConfig;
 import org.hswebframework.web.commons.entity.DataStatus;
 import org.hswebframework.web.commons.entity.factory.EntityFactory;
@@ -64,6 +66,7 @@ import java.io.OutputStream;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.stream.Stream;
 
 /**
@@ -91,11 +94,17 @@ public class SpringBootExample
                 MultipartFile.class,
                 MultipartFile[].class
         };
-        return loggerInfo -> System.out.println("有请求啦:" + JSON.toJSONString(loggerInfo.toSimpleMap(obj -> {
-            if (Stream.of(excludes).anyMatch(aClass -> aClass.isInstance(obj)))
-                return obj.getClass().getName();
-            return JSON.toJSONString(obj);
-        })));
+        return loggerInfo -> {
+            Map<String, Object> loggerMap = loggerInfo.toSimpleMap(obj -> {
+                if (Stream.of(excludes).anyMatch(aClass -> aClass.isInstance(obj)))
+                    return obj.getClass().getName();
+                return JSON.toJSONString(obj);
+            });
+            loggerMap.put("userToken", UserTokenHolder.currentToken());
+
+            System.out.println(JSON.toJSONString(loggerMap, SerializerFeature.SortField, SerializerFeature.PrettyFormat));
+
+        };
     }
 
     @Bean

+ 4 - 4
hsweb-starter/hsweb-spring-boot-starter/src/main/java/org/hswebframework/web/starter/RestControllerExceptionTranslator.java

@@ -55,7 +55,7 @@ public class RestControllerExceptionTranslator {
     @ResponseStatus(HttpStatus.BAD_REQUEST)
     @ResponseBody
     ResponseMessage<Object> handleException(org.hsweb.ezorm.rdb.exception.ValidationException exception) {
-        return ResponseMessage.error(400, exception.getMessage()).data(exception.getValidateResult());
+        return ResponseMessage.error(400, exception.getMessage()).result(exception.getValidateResult());
     }
 
     @ExceptionHandler(ValidationException.class)
@@ -63,7 +63,7 @@ public class RestControllerExceptionTranslator {
     @ResponseBody
     ResponseMessage<List<ValidateResults.Result>> handleException(ValidationException exception) {
         return ResponseMessage.<List<ValidateResults.Result>>error(400, exception.getMessage())
-                .data(exception.getResults());
+                .result(exception.getResults());
     }
 
     @ExceptionHandler(BusinessException.class)
@@ -80,7 +80,7 @@ public class RestControllerExceptionTranslator {
     @ResponseStatus(HttpStatus.UNAUTHORIZED)
     @ResponseBody
     ResponseMessage handleException(UnAuthorizedException exception) {
-        return ResponseMessage.error(401, exception.getMessage());
+        return ResponseMessage.error(401, exception.getMessage()).result(exception.getState());
     }
 
     @ExceptionHandler(AccessDenyException.class)
@@ -108,7 +108,7 @@ public class RestControllerExceptionTranslator {
                 .map(FieldError.class::cast)
                 .forEach(fieldError -> results.addResult(fieldError.getField(), fieldError.getDefaultMessage()));
 
-        return ResponseMessage.error(400, results.getResults().size() == 0 ? e.getMessage() : results.getResults().get(0).getMessage()).data(results.getResults());
+        return ResponseMessage.error(400, results.getResults().size() == 0 ? e.getMessage() : results.getResults().get(0).getMessage()).result(results.getResults());
     }
 //    @ExceptionHandler(Throwable.class)
 //    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)

+ 3 - 6
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-controller/src/main/java/org/hswebframework/web/controller/authorization/AuthorizationController.java

@@ -23,7 +23,6 @@ import io.swagger.annotations.ApiParam;
 import org.hswebframework.web.BusinessException;
 import org.hswebframework.web.NotFoundException;
 import org.hswebframework.web.authorization.Authentication;
-//import org.hswebframework.web.authorization.AuthenticationInitializeService;
 import org.hswebframework.web.authorization.AuthenticationManager;
 import org.hswebframework.web.authorization.annotation.Authorize;
 import org.hswebframework.web.authorization.listener.AuthorizationListenerDispatcher;
@@ -58,15 +57,13 @@ public class AuthorizationController {
     @Autowired
     private UserService userService;
 
-//    @Autowired
-//    private AuthenticationInitializeService authenticationInitializeService;
-
     @Autowired
-    private AuthenticationManager           authenticationManager;
+    private AuthenticationManager authenticationManager;
+
     @Autowired
     private AuthorizationListenerDispatcher authorizationListenerDispatcher;
 
-    @GetMapping({"/login-out","/sign-out","/exit"})
+    @GetMapping({"/login-out", "/sign-out", "/exit"})
     @Authorize
     @ApiOperation("退出当前登录")
     public ResponseMessage exit(@ApiParam(hidden = true) Authentication authentication) {

+ 28 - 0
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-controller/src/main/java/org/hswebframework/web/controller/authorization/UserController.java

@@ -23,6 +23,9 @@ import org.hswebframework.web.authorization.Authentication;
 import org.hswebframework.web.authorization.Permission;
 import org.hswebframework.web.authorization.annotation.Authorize;
 import org.hswebframework.web.authorization.exception.UnAuthorizedException;
+import org.hswebframework.web.authorization.token.TokenState;
+import org.hswebframework.web.authorization.token.UserToken;
+import org.hswebframework.web.authorization.token.UserTokenManager;
 import org.hswebframework.web.commons.entity.PagerResult;
 import org.hswebframework.web.commons.entity.param.QueryParamEntity;
 import org.hswebframework.web.controller.CreateController;
@@ -36,10 +39,13 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 
+import java.util.List;
+
 import static org.hswebframework.web.controller.message.ResponseMessage.ok;
 
 /**
  * 用户管理控制器
+ *
  * @author zhouhao
  */
 @RestController
@@ -53,6 +59,8 @@ public class UserController implements
 
     private UserService userService;
 
+    private UserTokenManager userTokenManager;
+
     @Override
     @SuppressWarnings("unchecked")
     public UserService getService() {
@@ -64,6 +72,26 @@ public class UserController implements
         this.userService = userService;
     }
 
+    @Autowired
+    public void setUserTokenManager(UserTokenManager userTokenManager) {
+        this.userTokenManager = userTokenManager;
+    }
+
+    @GetMapping("/tokens")
+    @Authorize(action = Permission.ACTION_QUERY)
+    @AccessLogger("获取所有已登录用户的信息")
+    public ResponseMessage<List<UserToken>> userTokens() {
+        return ok(userTokenManager.allLoggedUser());
+    }
+
+    @PutMapping("/tokens/{token}/{state}")
+    @Authorize(action = "change-state")
+    @AccessLogger("修改token的状态")
+    public ResponseMessage<List<UserToken>> makeOffline(@PathVariable String token, @PathVariable TokenState state) {
+        userTokenManager.changeTokenState(token, state);
+        return ok();
+    }
+
     @Override
     public ResponseMessage<PagerResult<UserEntity>> list(QueryParamEntity param) {
         param.excludes("password", "salt");