From b5a8cf712cf3f5db912273840ef37bbb3c9e2126 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 18 Aug 2017 17:06:13 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=A7=E7=BB=AD=E4=BC=98=E5=8C=96=E6=9D=83?= =?UTF-8?q?=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/UnAuthorizedException.java | 20 +++++++++++-- .../token/MemoryUserTokenManager.java | 18 +++++++++--- .../authorization/token/SimpleUserToken.java | 15 +++++----- .../web/authorization/token/UserToken.java | 3 +- .../authorization/token/UserTokenManager.java | 24 ++++++++++++++-- .../handler/DefaultAuthorizingHandler.java | 2 +- .../access/OwnCreatedDataAccessHandler.java | 2 +- .../web/UserTokenAuthenticationSupplier.java | 6 +++- .../basic/web/WebUserTokenInterceptor.java | 9 ++---- .../controller/message/ResponseMessage.java | 8 +++--- .../web/example/simple/SpringBootExample.java | 19 +++++++++---- .../RestControllerExceptionTranslator.java | 8 +++--- .../AuthorizationController.java | 9 ++---- .../authorization/UserController.java | 28 +++++++++++++++++++ 14 files changed, 124 insertions(+), 47 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/exception/UnAuthorizedException.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/exception/UnAuthorizedException.java index d69f9fc30..563622880 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/exception/UnAuthorizedException.java +++ b/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(String message) { + public UnAuthorizedException(TokenState state) { + this("{un_authorization}", state); + } + + 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; } } diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/MemoryUserTokenManager.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/MemoryUserTokenManager.java index 56a4c54b0..fb7bc9a1c 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/MemoryUserTokenManager.java +++ b/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); diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/SimpleUserToken.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/SimpleUserToken.java index 6f308d09b..97d9c40ad 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/SimpleUserToken.java +++ b/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(); } } diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserToken.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserToken.java index 6031f8c7f..f7133af26 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserToken.java +++ b/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 { return getState() == TokenState.offline; } - default void validate() { + default boolean validate() { if (!isEffective()) { throw new UnAuthorizedException(getState()); } + return true; } @Override diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserTokenManager.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserTokenManager.java index 70a26d088..c52f34418 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserTokenManager.java +++ b/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); diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/DefaultAuthorizingHandler.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/DefaultAuthorizingHandler.java index 265e244ec..545c6fc5a 100644 --- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/DefaultAuthorizingHandler.java +++ b/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 = context.getAuthentication().getPermissions() diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/access/OwnCreatedDataAccessHandler.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/access/OwnCreatedDataAccessHandler.java index c79d50c6b..e557d1d01 100644 --- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/access/OwnCreatedDataAccessHandler.java +++ b/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()); diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/UserTokenAuthenticationSupplier.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/UserTokenAuthenticationSupplier.java index c408a2a8d..c5f58cedd 100644 --- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/UserTokenAuthenticationSupplier.java +++ b/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))); } } diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/WebUserTokenInterceptor.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/WebUserTokenInterceptor.java index 1070f2fea..5f0bd4b0b 100644 --- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/WebUserTokenInterceptor.java +++ b/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; } diff --git a/hsweb-commons/hsweb-commons-controller/src/main/java/org/hswebframework/web/controller/message/ResponseMessage.java b/hsweb-commons/hsweb-commons-controller/src/main/java/org/hswebframework/web/controller/message/ResponseMessage.java index e86d7e77d..39d04782c 100644 --- a/hsweb-commons/hsweb-commons-controller/src/main/java/org/hswebframework/web/controller/message/ResponseMessage.java +++ b/hsweb-commons/hsweb-commons-controller/src/main/java/org/hswebframework/web/controller/message/ResponseMessage.java @@ -82,9 +82,9 @@ public class ResponseMessage implements Serializable { return this; } - public static ResponseMessage ok(T data) { + public static ResponseMessage ok(T result) { return new ResponseMessage() - .data(data) + .result(result) .putTimeStamp() .status(200); } @@ -94,8 +94,8 @@ public class ResponseMessage implements Serializable { // return this; // } - public ResponseMessage data(T data) { - this.result = data; + public ResponseMessage result(T result) { + this.result = result; return this; } diff --git a/hsweb-examples/hsweb-examples-simple/src/main/java/org/hswebframework/web/example/simple/SpringBootExample.java b/hsweb-examples/hsweb-examples-simple/src/main/java/org/hswebframework/web/example/simple/SpringBootExample.java index d6fefbd2d..3dafa0d0d 100644 --- a/hsweb-examples/hsweb-examples-simple/src/main/java/org/hswebframework/web/example/simple/SpringBootExample.java +++ b/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 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 diff --git a/hsweb-starter/hsweb-spring-boot-starter/src/main/java/org/hswebframework/web/starter/RestControllerExceptionTranslator.java b/hsweb-starter/hsweb-spring-boot-starter/src/main/java/org/hswebframework/web/starter/RestControllerExceptionTranslator.java index 4d72435f2..c588241e8 100644 --- a/hsweb-starter/hsweb-spring-boot-starter/src/main/java/org/hswebframework/web/starter/RestControllerExceptionTranslator.java +++ b/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 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> handleException(ValidationException exception) { return ResponseMessage.>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) diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-controller/src/main/java/org/hswebframework/web/controller/authorization/AuthorizationController.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-controller/src/main/java/org/hswebframework/web/controller/authorization/AuthorizationController.java index a97ca5cd9..0e0829c0e 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-controller/src/main/java/org/hswebframework/web/controller/authorization/AuthorizationController.java +++ b/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) { diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-controller/src/main/java/org/hswebframework/web/controller/authorization/UserController.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-controller/src/main/java/org/hswebframework/web/controller/authorization/UserController.java index 5c46a4254..84a3fcdfc 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-controller/src/main/java/org/hswebframework/web/controller/authorization/UserController.java +++ b/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> userTokens() { + return ok(userTokenManager.allLoggedUser()); + } + + @PutMapping("/tokens/{token}/{state}") + @Authorize(action = "change-state") + @AccessLogger("修改token的状态") + public ResponseMessage> makeOffline(@PathVariable String token, @PathVariable TokenState state) { + userTokenManager.changeTokenState(token, state); + return ok(); + } + @Override public ResponseMessage> list(QueryParamEntity param) { param.excludes("password", "salt");