瀏覽代碼

i18n 支持

zhou-hao 3 年之前
父節點
當前提交
e664d68023
共有 22 個文件被更改,包括 218 次插入45 次删除
  1. 1 1
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/TwoFactor.java
  2. 10 2
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/exception/AccessDenyException.java
  3. 6 1
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/exception/AuthenticationException.java
  4. 2 1
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/exception/UnAuthorizedException.java
  5. 1 1
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/DefaultUserTokenManager.java
  6. 7 7
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/TokenState.java
  7. 1 1
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/redis/RedisUserTokenManager.java
  8. 14 0
      hsweb-authorization/hsweb-authorization-api/src/main/resources/i18n/messages_zh_CN.properties
  9. 1 1
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinition.java
  10. 3 3
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/twofactor/TwoFactorHandlerInterceptorAdapter.java
  11. 3 3
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/AuthorizationController.java
  12. 13 5
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonErrorControllerAdvice.java
  13. 27 5
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonWebFluxConfiguration.java
  14. 9 9
      hsweb-core/src/main/java/org/hswebframework/web/exception/BusinessException.java
  15. 27 0
      hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java
  16. 3 3
      hsweb-core/src/main/java/org/hswebframework/web/exception/NotFoundException.java
  17. 67 0
      hsweb-core/src/main/java/org/hswebframework/web/i18n/LocaleUtils.java
  18. 18 0
      hsweb-core/src/main/java/org/hswebframework/web/i18n/WebFluxLocaleFilter.java
  19. 2 0
      hsweb-core/src/main/resources/i18n/messages_zh_CN.properties
  20. 1 1
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/configuration/PermissionProperties.java
  21. 1 1
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionUserService.java
  22. 1 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/resources/i18n/messages_zh_CN.properties

+ 1 - 1
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/TwoFactor.java

@@ -55,5 +55,5 @@ public @interface TwoFactor {
      * @return 错误提示
      * @since 3.0.6
      */
-    String message() default "需要进行双因子验证";
+    String message() default "assert.verify_code_error";
 }

+ 10 - 2
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/exception/AccessDenyException.java

@@ -1,9 +1,12 @@
 package org.hswebframework.web.authorization.exception;
 
 import lombok.Getter;
+import org.hswebframework.web.exception.I18nSupportException;
 import org.springframework.http.HttpStatus;
 import org.springframework.web.bind.annotation.ResponseStatus;
 
+import java.util.Set;
+
 /**
  * 权限验证异常
  *
@@ -11,7 +14,7 @@ import org.springframework.web.bind.annotation.ResponseStatus;
  * @since 3.0
  */
 @ResponseStatus(HttpStatus.FORBIDDEN)
-public class AccessDenyException extends RuntimeException {
+public class AccessDenyException extends I18nSupportException {
 
     private static final long serialVersionUID = -5135300127303801430L;
 
@@ -19,16 +22,21 @@ public class AccessDenyException extends RuntimeException {
     private String code;
 
     public AccessDenyException() {
-        this("权限不足,拒绝访问!");
+        this("error.access_denied");
     }
 
     public AccessDenyException(String message) {
         super(message);
     }
 
+    public AccessDenyException(String permission, Set<String> actions) {
+        super("error.permission_denied", permission, actions);
+    }
+
     public AccessDenyException(String message, String code) {
         this(message, code, null);
     }
+
     public AccessDenyException(String message, Throwable cause) {
         this(message, "access_denied", cause);
     }

+ 6 - 1
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/exception/AuthenticationException.java

@@ -1,9 +1,10 @@
 package org.hswebframework.web.authorization.exception;
 
 import lombok.Getter;
+import org.hswebframework.web.exception.I18nSupportException;
 
 @Getter
-public class AuthenticationException extends RuntimeException {
+public class AuthenticationException extends I18nSupportException {
 
 
     public static String ILLEGAL_PASSWORD = "illegal_password";
@@ -13,6 +14,10 @@ public class AuthenticationException extends RuntimeException {
 
     private final String code;
 
+    public AuthenticationException(String code) {
+        this(code, "error." + code);
+    }
+
     public AuthenticationException(String code, String message) {
         super(message);
         this.code = code;

+ 2 - 1
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/exception/UnAuthorizedException.java

@@ -19,6 +19,7 @@
 package org.hswebframework.web.authorization.exception;
 
 import org.hswebframework.web.authorization.token.TokenState;
+import org.hswebframework.web.exception.I18nSupportException;
 import org.springframework.http.HttpStatus;
 import org.springframework.web.bind.annotation.ResponseStatus;
 
@@ -29,7 +30,7 @@ import org.springframework.web.bind.annotation.ResponseStatus;
  * @since 3.0
  */
 @ResponseStatus(HttpStatus.UNAUTHORIZED)
-public class UnAuthorizedException extends RuntimeException {
+public class UnAuthorizedException extends I18nSupportException {
     private static final long serialVersionUID = 2422918455013900645L;
 
     private final TokenState state;

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

@@ -253,7 +253,7 @@ public class DefaultUserTokenManager implements UserTokenManager {
                         .flatMap(this::checkTimeout)
                         .filterWhen(t -> {
                             if (t.isNormal()) {
-                                return Mono.error(new AccessDenyException("该用户已在其他地方登陆"));
+                                return Mono.error(new AccessDenyException("error.logged_in_elsewhere"));
                             }
                             return Mono.empty();
                         })

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

@@ -13,30 +13,30 @@ public enum TokenState implements EnumDict<String> {
     /**
      * 正常,有效
      */
-    normal("normal","正常"),
+    normal("normal","message.token_state_normal"),
 
     /**
      * 已被禁止访问
      */
-    deny("deny", "已被禁止访问"),
+    deny("deny", "message.token_state_deny"),
 
     /**
      * 已过期
      */
-    expired("expired", "用户未登录"),
+    expired("expired", "message.token_state_expired"),
 
     /**
      * 已被踢下线
      * @see AllopatricLoginMode#offlineOther
      */
-    offline("offline", "用户已在其他地方登录"),
+    offline("offline", "message.token_state_offline"),
 
     /**
      * 锁定
      */
-    lock("lock", "登录状态已被锁定");
+    lock("lock", "message.token_state_lock");
 
-    private String value;
+    private final String value;
 
-    private String text;
+    private final String text;
 }

+ 1 - 1
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/redis/RedisUserTokenManager.java

@@ -244,7 +244,7 @@ public class RedisUserTokenManager implements UserTokenManager {
                         return userIsLoggedIn(userId)
                                 .flatMap(r -> {
                                     if (r) {
-                                        return Mono.error(new AccessDenyException("已在其他地方登录", TokenState.deny.getValue(), null));
+                                        return Mono.error(new AccessDenyException("error.logged_in_elsewhere", TokenState.deny.getValue(), null));
                                     }
                                     return doSign;
                                 });

+ 14 - 0
hsweb-authorization/hsweb-authorization-api/src/main/resources/i18n/messages_zh_CN.properties

@@ -0,0 +1,14 @@
+error.access_denied=权限不足,拒绝访问!
+error.permission_denied=当前用户无权限[{0}]:{1}
+error.logged_in_elsewhere=该用户已在其他地方登陆
+#
+message.token_state_normal=正常
+message.token_state_deny=已被禁止访问
+message.token_state_expired=用户未登录
+message.token_state_offline=用户已在其他地方登录
+message.token_state_lock=登录状态已被锁定
+#
+assert.need_two_factor_verify=需要双因子验证
+assert.username_must_not_be_empty=用户名不能为空
+assert.password_must_not_be_empty=密码不能为空
+assert.verify_code_error=验证码错误

+ 1 - 1
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinition.java

@@ -36,7 +36,7 @@ public class DefaultBasicAuthorizeDefinition implements AopAuthorizeDefinition {
     private ResourcesDefinition resources = new ResourcesDefinition();
     private DimensionsDefinition dimensions = new DimensionsDefinition();
 
-    private String message = "权限不足,拒绝访问";
+    private String message = "error.access_denied";
 
     private Phased phased;
 

+ 3 - 3
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/twofactor/TwoFactorHandlerInterceptorAdapter.java

@@ -22,7 +22,7 @@ import javax.servlet.http.HttpServletResponse;
 @AllArgsConstructor
 public class TwoFactorHandlerInterceptorAdapter extends HandlerInterceptorAdapter {
 
-    private TwoFactorValidatorManager validatorManager;
+    private final TwoFactorValidatorManager validatorManager;
 
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
@@ -45,9 +45,9 @@ public class TwoFactorHandlerInterceptorAdapter extends HandlerInterceptorAdapte
                 code = request.getHeader(factor.parameter());
             }
             if (StringUtils.isEmpty(code)) {
-                throw new NeedTwoFactorException(factor.message(), factor.provider());
+                throw new NeedTwoFactorException("assert.need_two_factor_verify", factor.provider());
             } else if (!validator.verify(code, factor.timeout())) {
-                throw new NeedTwoFactorException("验证码错误", factor.provider());
+                throw new NeedTwoFactorException(factor.message(), factor.provider());
             }
         }
         return super.preHandle(request, response, handler);

+ 3 - 3
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/AuthorizationController.java

@@ -85,8 +85,8 @@ public class AuthorizationController {
             String username_ = (String) parameters.get("username");
             String password_ = (String) parameters.get("password");
 
-            Assert.hasLength(username_, "用户名不能为空");
-            Assert.hasLength(password_, "密码不能为空");
+            Assert.hasLength(username_, "assert.username_must_not_be_empty");
+            Assert.hasLength(password_, "assert.password_must_not_be_empty");
 
             Function<String, Object> parameterGetter = parameters::get;
             return Mono.defer(() -> {
@@ -101,7 +101,7 @@ public class AuthorizationController {
                                     .publish(eventPublisher)
                                     .then(authenticationManager
                                             .authenticate(Mono.just(new PlainTextUsernamePasswordAuthenticationRequest(username, password)))
-                                            .switchIfEmpty(Mono.error(() -> new AuthenticationException(AuthenticationException.ILLEGAL_PASSWORD,"密码错误")))
+                                            .switchIfEmpty(Mono.error(() -> new AuthenticationException(AuthenticationException.ILLEGAL_PASSWORD)))
                                             .flatMap(auth -> {
                                                 //触发授权成功事件
                                                 AuthorizationSuccessEvent event = new AuthorizationSuccessEvent(auth, parameterGetter);

+ 13 - 5
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonErrorControllerAdvice.java

@@ -1,7 +1,6 @@
 package org.hswebframework.web.crud.web;
 
 import io.r2dbc.spi.R2dbcDataIntegrityViolationException;
-import io.r2dbc.spi.R2dbcNonTransientException;
 import lombok.extern.slf4j.Slf4j;
 import org.hswebframework.web.authorization.exception.AccessDenyException;
 import org.hswebframework.web.authorization.exception.AuthenticationException;
@@ -10,11 +9,11 @@ import org.hswebframework.web.authorization.token.TokenState;
 import org.hswebframework.web.exception.BusinessException;
 import org.hswebframework.web.exception.NotFoundException;
 import org.hswebframework.web.exception.ValidationException;
+import org.hswebframework.web.i18n.LocaleUtils;
 import org.hswebframework.web.logger.ReactiveLogger;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
-import org.springframework.core.Ordered;
+import org.springframework.context.MessageSource;
 import org.springframework.core.annotation.Order;
-import org.springframework.core.codec.DecodingException;
 import org.springframework.http.HttpStatus;
 import org.springframework.validation.BindException;
 import org.springframework.validation.FieldError;
@@ -40,11 +39,20 @@ import java.util.stream.Collectors;
 @Order
 public class CommonErrorControllerAdvice {
 
+
+    private final MessageSource messageSource;
+
+    public CommonErrorControllerAdvice(MessageSource messageSource) {
+        this.messageSource = messageSource;
+    }
+
     @ExceptionHandler
     @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
     public Mono<ResponseMessage<Object>> handleException(BusinessException e) {
-        return Mono.just(ResponseMessage.error(e.getCode(), e.getMessage()))
-                   .doOnEach(ReactiveLogger.onNext(r -> log.error(e.getMessage(), e)));
+        return LocaleUtils
+                .resolveThrowable(messageSource,
+                                  e,
+                                  (err, msg) -> ResponseMessage.error(err.getStatus(), err.getCode(), msg));
     }
 
     @ExceptionHandler

+ 27 - 5
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonWebFluxConfiguration.java

@@ -1,14 +1,22 @@
 package org.hswebframework.web.crud.web;
 
+import org.hswebframework.web.i18n.WebFluxLocaleFilter;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
 import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.MessageSource;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.context.i18n.LocaleContext;
+import org.springframework.context.support.ReloadableResourceBundleMessageSource;
 import org.springframework.core.ReactiveAdapterRegistry;
 import org.springframework.http.codec.ServerCodecConfigurer;
 import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
+import org.springframework.web.server.ServerWebExchange;
+import org.springframework.web.server.WebFilter;
+import org.springframework.web.server.WebFilterChain;
+import reactor.core.publisher.Mono;
 
 @Configuration
 @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
@@ -16,17 +24,31 @@ public class CommonWebFluxConfiguration {
 
     @Bean
     @ConditionalOnMissingBean
-    public CommonErrorControllerAdvice commonErrorControllerAdvice(){
-        return new CommonErrorControllerAdvice();
+    public CommonErrorControllerAdvice commonErrorControllerAdvice(MessageSource messageSource) {
+        return new CommonErrorControllerAdvice(messageSource);
     }
 
 
     @Bean
-    @ConditionalOnProperty(prefix = "hsweb.webflux.response-wrapper",name = "enabled",havingValue = "true",matchIfMissing = true)
+    @ConditionalOnProperty(prefix = "hsweb.webflux.response-wrapper", name = "enabled", havingValue = "true", matchIfMissing = true)
     @ConfigurationProperties(prefix = "hsweb.webflux.response-wrapper")
     public ResponseMessageWrapper responseMessageWrapper(ServerCodecConfigurer codecConfigurer,
                                                          RequestedContentTypeResolver resolver,
-                                                         ReactiveAdapterRegistry registry){
-        return new ResponseMessageWrapper(codecConfigurer.getWriters(),resolver,registry);
+                                                         ReactiveAdapterRegistry registry) {
+        return new ResponseMessageWrapper(codecConfigurer.getWriters(), resolver, registry);
     }
+
+    @Bean
+    public MessageSource messageSource() {
+        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
+        messageSource.setBasenames("i18n/messages");
+        messageSource.setDefaultEncoding("UTF-8");
+        return messageSource;
+    }
+
+    @Bean
+    public WebFilter localeWebFilter() {
+        return new WebFluxLocaleFilter();
+    }
+
 }

+ 9 - 9
hsweb-core/src/main/java/org/hswebframework/web/exception/BusinessException.java

@@ -26,7 +26,7 @@ import lombok.Getter;
  * @author zhouhao
  * @since 2.0
  */
-public class BusinessException extends RuntimeException {
+public class BusinessException extends I18nSupportException {
     private static final long serialVersionUID = 5441923856899380112L;
 
     @Getter
@@ -39,21 +39,21 @@ public class BusinessException extends RuntimeException {
         this(message, 500);
     }
 
-    public BusinessException(String message, String code) {
-        this(message, code, 500);
+    public BusinessException(String message, int status, Object... args) {
+        this(message, null, status, args);
     }
 
-    public BusinessException(String message, String code, int status) {
-        super(message);
-        this.code = code;
-        this.status = status;
+    public BusinessException(String message, String code, Object... args) {
+        this(message, code, 500, args);
     }
 
-    public BusinessException(String message, int status) {
-        super(message);
+    public BusinessException(String message, String code, int status, Object... args) {
+        super(message, args);
+        this.code = code;
         this.status = status;
     }
 
+
     public BusinessException(String message, Throwable cause) {
         super(message, cause);
     }

+ 27 - 0
hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java

@@ -0,0 +1,27 @@
+package org.hswebframework.web.exception;
+
+
+import lombok.Getter;
+
+@Getter
+public class I18nSupportException extends RuntimeException {
+
+    private final Object[] args;
+
+    public I18nSupportException(String code, Object... args) {
+        super(code);
+        this.args = args;
+    }
+
+    public I18nSupportException(String code, Throwable cause, Object... args) {
+        super(code, cause);
+        this.args = args;
+    }
+
+
+    @Override
+    public String getLocalizedMessage() {
+        // TODO: 2021/6/21
+        return super.getLocalizedMessage();
+    }
+}

+ 3 - 3
hsweb-core/src/main/java/org/hswebframework/web/exception/NotFoundException.java

@@ -24,11 +24,11 @@ import org.springframework.web.bind.annotation.ResponseStatus;
 
 @ResponseStatus(HttpStatus.NOT_FOUND)
 public class NotFoundException extends BusinessException {
-    public NotFoundException(String message) {
-        super(message, 404);
+    public NotFoundException(String message, Object... args) {
+        super(message, 404, args);
     }
 
     public NotFoundException() {
-        this("记录不存在");
+        this("error.not_found");
     }
 }

+ 67 - 0
hsweb-core/src/main/java/org/hswebframework/web/i18n/LocaleUtils.java

@@ -0,0 +1,67 @@
+package org.hswebframework.web.i18n;
+
+import org.hswebframework.web.exception.I18nSupportException;
+import org.springframework.context.MessageSource;
+import org.springframework.context.i18n.LocaleContext;
+import org.springframework.context.i18n.SimpleLocaleContext;
+import reactor.core.publisher.Mono;
+
+import java.util.Locale;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+public class LocaleUtils {
+
+    public static final LocaleContext DEFAULT_CONTEXT = new SimpleLocaleContext(Locale.getDefault());
+
+    public static Mono<LocaleContext> reactive() {
+        return Mono
+                .subscriberContext()
+                .map(ctx -> ctx
+                        .<LocaleContext>getOrEmpty(LocaleContext.class)
+                        .orElse(DEFAULT_CONTEXT));
+    }
+
+
+    public static <S extends I18nSupportException, R> Mono<R> resolveThrowable(MessageSource messageSource,
+                                                                               S source,
+                                                                               BiFunction<S, String, R> mapper) {
+        return doWithReactive(messageSource, source, Throwable::getMessage, mapper, source.getArgs());
+    }
+
+    public static <S extends Throwable, R> Mono<R> resolveThrowable(MessageSource messageSource,
+                                                                    S source,
+                                                                    BiFunction<S, String, R> mapper,
+                                                                    Object... args) {
+        return doWithReactive(messageSource, source, Throwable::getMessage, mapper, args);
+    }
+
+    public static <S, R> Mono<R> doWithReactive(MessageSource messageSource,
+                                                S source,
+                                                Function<S, String> message,
+                                                BiFunction<S, String, R> mapper,
+                                                Object... args) {
+        return reactive()
+                .map(ctx -> {
+                    String msg = message.apply(source);
+                    String newMsg = resolveMessage(messageSource, msg, ctx.getLocale(), msg, args);
+                    return mapper.apply(source, newMsg);
+                });
+    }
+
+    public static Mono<String> reactiveMessage(MessageSource messageSource,
+                                               String code,
+                                               Object... args) {
+        return reactive()
+                .map(ctx -> resolveMessage(messageSource, code, ctx.getLocale(), code, args));
+    }
+
+    public static String resolveMessage(MessageSource messageSource,
+                                        String code,
+                                        Locale locale,
+                                        String defaultMessage,
+                                        Object... args) {
+        return messageSource.getMessage(code, args, defaultMessage, locale);
+    }
+
+}

+ 18 - 0
hsweb-core/src/main/java/org/hswebframework/web/i18n/WebFluxLocaleFilter.java

@@ -0,0 +1,18 @@
+package org.hswebframework.web.i18n;
+
+import org.springframework.context.i18n.LocaleContext;
+import org.springframework.lang.NonNull;
+import org.springframework.web.server.ServerWebExchange;
+import org.springframework.web.server.WebFilter;
+import org.springframework.web.server.WebFilterChain;
+import reactor.core.publisher.Mono;
+
+public class WebFluxLocaleFilter implements WebFilter {
+    @Override
+    @NonNull
+    public Mono<Void> filter(@NonNull ServerWebExchange exchange, WebFilterChain chain) {
+        return chain
+                .filter(exchange)
+                .subscriberContext(ctx -> ctx.put(LocaleContext.class, exchange.getLocaleContext()));
+    }
+}

+ 2 - 0
hsweb-core/src/main/resources/i18n/messages_zh_CN.properties

@@ -0,0 +1,2 @@
+error.not_found=数据不存在
+error.cant_create_instance=无法创建实例:{0}

+ 1 - 1
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/configuration/PermissionProperties.java

@@ -75,7 +75,7 @@ public class PermissionProperties {
                                               .map(Permission::getActions)
                                               .orElseGet(Collections::emptySet));
 
-                    throw new AccessDenyException("当前用户无权限:" + setting.getPermission() + "" +actions);
+                    throw new AccessDenyException(setting.getPermission(), actions);
                 }
             };
 

+ 1 - 1
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionUserService.java

@@ -59,7 +59,7 @@ public class DefaultDimensionUserService extends GenericReactiveCrudService<Dime
         return this
                 .publishEvent(entityPublisher, DimensionBindEvent::new)
                 .as(super::insert)
-                .onErrorMap(DuplicateKeyException.class, (err) -> new BusinessException("重复的绑定请求"));
+                .onErrorMap(DuplicateKeyException.class, (err) -> new BusinessException("error.duplicate_key"));
     }
 
     @Override

+ 1 - 0
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/resources/i18n/messages_zh_CN.properties

@@ -0,0 +1 @@
+error.duplicate_key=重复的请求