diff --git a/opsli-base-support/opsli-common/src/main/java/org/opsli/common/constants/SignConstants.java b/opsli-base-support/opsli-common/src/main/java/org/opsli/common/constants/SignConstants.java
index 7b4a3bd1..17b3577c 100644
--- a/opsli-base-support/opsli-common/src/main/java/org/opsli/common/constants/SignConstants.java
+++ b/opsli-base-support/opsli-common/src/main/java/org/opsli/common/constants/SignConstants.java
@@ -1,24 +1,7 @@
-/**
- * Copyright 2020 OPSLI 快速开发平台 https://www.opsli.com
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
package org.opsli.common.constants;
/**
- * @BelongsProject: opsli-boot
- * @BelongsPackage: org.opsli.common.constants
- * @Author: Parker
+ * @Author: 周鹏程
* @CreateTime: 2020-09-16 17:42
* @Description: 签名
*/
@@ -33,4 +16,10 @@ public interface SignConstants {
/** 时间戳 */
String TIMESTAMP = "timestamp";
+ /** 其他信息 */
+ String OTHER = "other";
+
+ /** 签名 类型 */
+ String TYPE = "type";
+
}
diff --git a/opsli-base-support/opsli-common/src/main/java/org/opsli/common/constants/TokenTypeConstants.java b/opsli-base-support/opsli-common/src/main/java/org/opsli/common/constants/TokenTypeConstants.java
new file mode 100644
index 00000000..18099dd9
--- /dev/null
+++ b/opsli-base-support/opsli-common/src/main/java/org/opsli/common/constants/TokenTypeConstants.java
@@ -0,0 +1,16 @@
+package org.opsli.common.constants;
+
+/**
+ * @Author: 周鹏程
+ * @CreateTime: 2020-09-16 17:42
+ * @Description: Token类型
+ */
+public interface TokenTypeConstants {
+
+ /** 系统内部TOKEN */
+ String TYPE_SYSTEM = "system";
+
+ /** 外部TOKEN */
+ String TYPE_EXTERNAL = "external";
+
+}
diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/conf/ShiroConfig.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/conf/ShiroConfig.java
index 514cb7d1..809815dd 100644
--- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/conf/ShiroConfig.java
+++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/conf/ShiroConfig.java
@@ -16,8 +16,13 @@
package org.opsli.core.conf;
import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ClassUtil;
+import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
+import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
@@ -25,21 +30,21 @@ import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.opsli.common.utils.Props;
-import org.opsli.core.security.shiro.filter.OAuth2Filter;
-import org.opsli.core.security.shiro.realm.OAuth2Realm;
+import org.opsli.core.security.shiro.authenticator.CustomModularRealmAuthenticator;
+import org.opsli.core.security.shiro.filter.CustomShiroFilter;
+import org.opsli.core.security.shiro.realm.FlagRealm;
import org.opsli.plugins.redis.conf.RedisPluginConfig;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
-import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import javax.servlet.Filter;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
+import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* Shiro配置
@@ -76,7 +81,7 @@ public class ShiroConfig {
//oauth过滤
Map filters = Maps.newHashMapWithExpectedSize(1);
- filters.put("oauth2", new OAuth2Filter());
+ filters.put("last_filter", new CustomShiroFilter());
shiroFilter.setFilters(filters);
Map filterMap = Maps.newLinkedHashMap();
@@ -106,7 +111,7 @@ public class ShiroConfig {
filterMap.put("/swagger-ui.html", "anon");
filterMap.put("/swagger-resources/**", "anon");
filterMap.put("/static/file/**", "anon");
- filterMap.put("/**", "oauth2");
+ filterMap.put("/**", "last_filter");
shiroFilter.setFilterChainDefinitionMap(filterMap);
@@ -122,16 +127,42 @@ public class ShiroConfig {
}
@Bean("securityManager")
- public DefaultWebSecurityManager securityManager(OAuth2Realm oAuth2Realm, SessionManager sessionManager,LettuceConnectionFactory lettuceConnectionFactory) {
+ public DefaultWebSecurityManager securityManager(SessionManager sessionManager) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
- securityManager.setRealm(oAuth2Realm);
securityManager.setSessionManager(sessionManager);
+
+ List realms = Lists.newArrayList();
+ // 拿到state包下 实现了 FlagRealm 接口的,所有子类
+ Set> clazzSet = ClassUtil.scanPackageBySuper(FlagRealm.class.getPackage().getName()
+ , FlagRealm.class
+ );
+ for (Class> aClass : clazzSet) {
+ // 位运算 去除抽象类
+ if((aClass.getModifiers() & Modifier.ABSTRACT) != 0){
+ continue;
+ }
+
+ try {
+ realms.add((Realm) aClass.newInstance());
+ } catch (Exception ignored){ }
+ }
+
+ if(CollUtil.isNotEmpty(realms)){
+ // 追加 Realms
+ securityManager.setRealms(realms);
+ }
+
return securityManager;
}
- @Bean
- public OAuth2Realm oAuth2Realm() {
- return new OAuth2Realm();
+ /**
+ * 针对多Realm,使用自定义身份验证器
+ */
+ @Bean("modularRealmAuthenticator")
+ public ModularRealmAuthenticator modularRealmAuthenticator(){
+ CustomModularRealmAuthenticator authenticator = new CustomModularRealmAuthenticator();
+ authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
+ return authenticator;
}
@@ -157,7 +188,7 @@ public class ShiroConfig {
/**
* 开启shiro权限注解生效
- * @param securityManager
+ * @param securityManager 安全管理器
* @return
*/
@Bean("authorizationAttributeSourceAdvisor")
diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/conf/SwaggerConfig.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/conf/SwaggerConfig.java
index 544c0913..f3077da0 100644
--- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/conf/SwaggerConfig.java
+++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/conf/SwaggerConfig.java
@@ -21,6 +21,7 @@ import com.google.common.collect.Lists;
import io.swagger.annotations.ApiOperation;
import org.opsli.core.utils.UserTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -47,6 +48,10 @@ import java.util.List;
@Import(BeanValidatorPluginsConfiguration.class)
public class SwaggerConfig {
+ /** 系统名称 */
+ @Value("${opsli.system-name:OPSLI 快速开发平台}")
+ private String systemName;
+
private final TypeResolver typeResolver;
@Autowired
@@ -87,7 +92,7 @@ public class SwaggerConfig {
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
// //大标题
- .title("Opsli-Boot 后台服务API接口文档")
+ .title(systemName + " 服务API接口文档")
// 版本号
.version("1.0")
// 描述
diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/handler/GlobalExceptionHandler.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/handler/GlobalExceptionHandler.java
index f4dc438a..fdecff44 100644
--- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/handler/GlobalExceptionHandler.java
+++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/handler/GlobalExceptionHandler.java
@@ -20,6 +20,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
+import org.apache.shiro.authc.pam.UnsupportedTokenException;
import org.apache.shiro.authz.AuthorizationException;
import org.opsli.api.base.result.ResultVo;
import org.opsli.common.exception.*;
@@ -143,6 +144,19 @@ public class GlobalExceptionHandler {
);
}
+ /**
+ * 拦截 自定义 Shiro 认证异常
+ */
+ @ExceptionHandler(UnsupportedTokenException.class)
+ @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+ @ResponseBody
+ public ResultVo> unsupportedTokenException(UnsupportedTokenException e) {
+ // 找不到认证授权器
+ return ResultVo.error(TokenMsg.EXCEPTION_NOT_REALM.getCode(),
+ TokenMsg.EXCEPTION_NOT_REALM.getMessage()
+ );
+ }
+
/**
* 拦截 自定义 Token 认证异常
diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/msg/TokenMsg.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/msg/TokenMsg.java
index b146f168..07aec728 100644
--- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/msg/TokenMsg.java
+++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/msg/TokenMsg.java
@@ -52,7 +52,9 @@ public enum TokenMsg implements BaseMsg {
* 其他
*/
EXCEPTION_USER_NULL(12200, "用户为空"),
- EXCEPTION_NOT_AUTH(12204, "无权访问该方法"),
+ EXCEPTION_NOT_AUTH(12201, "无权访问该方法"),
+ EXCEPTION_NOT_REALM(12202, "找不到认证授权器"),
+
;
private final int code;
diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/authenticator/CustomModularRealmAuthenticator.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/authenticator/CustomModularRealmAuthenticator.java
new file mode 100644
index 00000000..6010447d
--- /dev/null
+++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/authenticator/CustomModularRealmAuthenticator.java
@@ -0,0 +1,44 @@
+package org.opsli.core.security.shiro.authenticator;
+
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
+import org.apache.shiro.authc.pam.UnsupportedTokenException;
+import org.apache.shiro.realm.Realm;
+
+import java.util.Collection;
+
+/**
+ * 自定义身份验证器,根据登录使用的Token匹配调用对应的Realm
+ * @author Parker
+ */
+public class CustomModularRealmAuthenticator extends ModularRealmAuthenticator {
+
+ /**
+ * 自定义Realm的分配策略
+ * 通过realm.supports()方法匹配对应的Realm,因此才要在Realm中重写supports()方法
+ * @param realms
+ * @param token
+ * @return
+ */
+ @Override
+ protected AuthenticationInfo doMultiRealmAuthentication(Collection realms, AuthenticationToken token) {
+ // 判断getRealms()是否返回为空
+ assertRealmsConfigured();
+
+ // 通过supports()方法,匹配对应的Realm
+ Realm uniqueRealm = null;
+ for (Realm realm : realms) {
+ if (realm.supports(token)) {
+ uniqueRealm = realm;
+ break;
+ }
+ }
+
+ if (uniqueRealm == null) {
+ throw new UnsupportedTokenException();
+ }
+ return uniqueRealm.getAuthenticationInfo(token);
+ }
+
+}
diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/filter/CustomShiroFilter.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/filter/CustomShiroFilter.java
new file mode 100644
index 00000000..9106e2f6
--- /dev/null
+++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/filter/CustomShiroFilter.java
@@ -0,0 +1,108 @@
+package org.opsli.core.security.shiro.filter;
+
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
+import org.opsli.api.base.result.ResultVo;
+import org.opsli.common.constants.SignConstants;
+import org.opsli.common.constants.TokenTypeConstants;
+import org.opsli.core.msg.TokenMsg;
+import org.opsli.core.security.shiro.token.ExternalToken;
+import org.opsli.core.security.shiro.token.OAuth2Token;
+import org.opsli.core.utils.JwtUtil;
+import org.opsli.core.utils.UserTokenUtil;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * oauth2过滤器
+ *
+ * 就是因为,以前单机,页面的挑转自己能控制,失败的时候定一个错误码:401,
+ *
+ * 集中登录,集中授权,
+ *
+ * @author 孙志强
+
+ * @date 2017-05-20 13:00
+ */
+public class CustomShiroFilter extends AuthenticatingFilter {
+
+ @Override
+ protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {
+ //获取请求token
+ String token = UserTokenUtil.getRequestToken((HttpServletRequest) request);
+
+ if(StringUtils.isBlank(token)){
+ return null;
+ }
+
+ // 分析token
+ String claim = JwtUtil.getClaim(token, SignConstants.TYPE);
+
+ // 第三方登录
+ if(TokenTypeConstants.TYPE_EXTERNAL.equals(claim)){
+ return new ExternalToken(token);
+ }
+ // .... 追加登录方式
+
+ return new OAuth2Token(token);
+ }
+
+ @Override
+ protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
+ if(((HttpServletRequest) request).getMethod().equals(RequestMethod.OPTIONS.name())){
+ return true;
+ }
+ // remeberMe ,remeberMe特殊页面,需要授权,
+
+ return false;
+ }
+
+ @Override
+ protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
+ HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+ //获取请求token,如果token不存在,直接返回401
+ String token = UserTokenUtil.getRequestToken((HttpServletRequest) request);
+ if(StringUtils.isBlank(token)){
+ HttpServletResponse httpResponse = (HttpServletResponse) response;
+ httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
+ httpResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
+ httpResponse.setHeader("Access-Control-Allow-Origin", httpServletRequest.getHeader("Origin"));
+ httpResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
+ httpResponse.setContentType("application/json; charset=utf-8");
+ // 401 Token失效,请重新登录
+ ResultVo error = ResultVo.error(TokenMsg.EXCEPTION_TOKEN_LOSE_EFFICACY.getCode(),
+ TokenMsg.EXCEPTION_TOKEN_LOSE_EFFICACY.getMessage());
+ httpResponse.getWriter().print(error.toJsonStr());
+ return false;
+ }
+
+ return executeLogin(request, response);
+ }
+
+ @Override
+ protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {
+ HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+ HttpServletResponse httpResponse = (HttpServletResponse) response;
+ httpResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
+ httpResponse.setHeader("Access-Control-Allow-Origin", httpServletRequest.getHeader("Origin"));
+ httpResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
+ httpResponse.setContentType("application/json; charset=utf-8");
+
+ try {
+ //处理登录失败的异常
+ Throwable throwable = e.getCause() == null ? e : e.getCause();
+ ResultVo error = ResultVo.error(401, throwable.getMessage());
+ httpResponse.getWriter().print(error.toJsonStr());
+ } catch (IOException ignored) {}
+ return false;
+ }
+
+}
diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/realm/ExternalRealm.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/realm/ExternalRealm.java
new file mode 100644
index 00000000..16f9b81d
--- /dev/null
+++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/realm/ExternalRealm.java
@@ -0,0 +1,54 @@
+package org.opsli.core.security.shiro.realm;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.realm.AuthorizingRealm;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.opsli.common.exception.TokenException;
+import org.opsli.core.security.shiro.token.ExternalToken;
+import org.springframework.stereotype.Component;
+
+
+/**
+ * 对外接口 认证
+ *
+ * @author 周鹏程
+
+ * @date 2020-12-29 14:00
+ */
+@Component
+@Slf4j
+public class ExternalRealm extends AuthorizingRealm implements FlagRealm {
+
+ /** 账号锁定状态 */
+ public static final char LOCK_VAL = '1';
+
+ @Override
+ public boolean supports(AuthenticationToken token) {
+ return token instanceof ExternalToken;
+ }
+
+ /**
+ * 授权(验证权限时调用)
+ */
+ @Override
+ protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
+ // TODO 待处理
+ return null;
+ }
+
+ /**
+ * 对外认证(登录时调用)
+ */
+ @Override
+ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
+ throws AuthenticationException, TokenException {
+ // TODO 待处理
+
+ return null;
+ }
+
+}
diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/realm/FlagRealm.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/realm/FlagRealm.java
new file mode 100644
index 00000000..69a41b2e
--- /dev/null
+++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/realm/FlagRealm.java
@@ -0,0 +1,11 @@
+package org.opsli.core.security.shiro.realm;
+
+/**
+ * @BelongsProject: think-bboss-parent
+ * @BelongsPackage: com.think.bboss.core.shiro.realm
+ * @Author: Parker
+ * @CreateTime: 2020-12-29 20:10
+ * @Description: Realm 识别类 勿删
+ */
+public interface FlagRealm {
+}
diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/realm/OAuth2Realm.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/realm/OAuth2Realm.java
index 5c56f8f8..b146d748 100644
--- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/realm/OAuth2Realm.java
+++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/realm/OAuth2Realm.java
@@ -30,7 +30,7 @@ import java.util.List;
*/
@Component
@Slf4j
-public class OAuth2Realm extends AuthorizingRealm {
+public class OAuth2Realm extends AuthorizingRealm implements FlagRealm {
/** 账号锁定状态 */
public static final String LOCK_VAL = "1";
diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/token/JwtToken.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/token/ExternalToken.java
similarity index 64%
rename from opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/token/JwtToken.java
rename to opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/token/ExternalToken.java
index 44885300..5f48a854 100644
--- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/token/JwtToken.java
+++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/token/ExternalToken.java
@@ -4,16 +4,17 @@ package org.opsli.core.security.shiro.token;
import org.apache.shiro.authc.AuthenticationToken;
/**
- * jwt token
+ * 第三方接口 token
*
- * @author parker
+ * @author 周鹏程
* @date 2017-05-20 13:22
*/
-public class JwtToken implements AuthenticationToken {
- private String token;
+public class ExternalToken implements AuthenticationToken {
- public JwtToken(String token){
+ private final String token;
+
+ public ExternalToken(String token){
this.token = token;
}
@@ -26,4 +27,5 @@ public class JwtToken implements AuthenticationToken {
public Object getCredentials() {
return token;
}
+
}
diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/token/OAuth2Token.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/token/OAuth2Token.java
index 061ae7e9..951074ca 100644
--- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/token/OAuth2Token.java
+++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/security/shiro/token/OAuth2Token.java
@@ -11,7 +11,8 @@ import org.apache.shiro.authc.AuthenticationToken;
* @date 2017-05-20 13:22
*/
public class OAuth2Token implements AuthenticationToken {
- private String token;
+
+ private final String token;
public OAuth2Token(String token){
this.token = token;
@@ -26,4 +27,5 @@ public class OAuth2Token implements AuthenticationToken {
public Object getCredentials() {
return token;
}
+
}
diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/JwtUtil.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/JwtUtil.java
index 70143e95..0598e160 100644
--- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/JwtUtil.java
+++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/JwtUtil.java
@@ -8,6 +8,7 @@ import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.opsli.common.constants.SignConstants;
+import org.opsli.common.constants.TokenTypeConstants;
import org.opsli.common.exception.JwtException;
import org.opsli.common.utils.Props;
import org.opsli.core.msg.JwtMsg;
@@ -79,10 +80,12 @@ public final class JwtUtil {
/**
* 生成签名
+ * @param tokenType token类型
* @param account 帐号
+ * @param userId 用户ID
* @return java.lang.String 返回加密的Token
*/
- public static String sign(String account, String userId) {
+ public static String sign(String tokenType, String account, String userId) {
try {
// 帐号加JWT私钥加密
String secret = account + Base64ConvertUtil.decode(ENCRYPT_JWT_KEY);
@@ -91,6 +94,7 @@ public final class JwtUtil {
Algorithm algorithm = Algorithm.HMAC256(secret);
// 附带account帐号信息
return JWT.create()
+ .withClaim(SignConstants.TYPE, tokenType)
.withClaim(SignConstants.ACCOUNT, account)
.withClaim(SignConstants.USER_ID, userId)
.withClaim(SignConstants.TIMESTAMP, String.valueOf(System.currentTimeMillis()))
@@ -106,7 +110,7 @@ public final class JwtUtil {
public static void main(String[] args) {
- String aaaaaa = JwtUtil.sign("aaaaaa","123123");
+ String aaaaaa = JwtUtil.sign(TokenTypeConstants.TYPE_SYSTEM, "aaaaaa","123123");
boolean verify = JwtUtil.verify(aaaaaa);
System.out.println(aaaaaa);
diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/SpringContextHolder.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/SpringContextHolder.java
index 8d629fbe..34bbb63d 100644
--- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/SpringContextHolder.java
+++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/SpringContextHolder.java
@@ -5,15 +5,20 @@ import org.apache.commons.lang3.Validate;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Lazy;
+import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
+
/**
- * 以静态变量保存Spring ApplicationContext, 可在任何代码任何地方任何时候取出ApplicaitonContext.
+ * 以静态变量保存Spring ApplicationContext, 可在任何代码任何地方任何时候取出ApplicationContext.
*
+ * 针对项目 启动后好使, 项目启动前 Bean注册时不好使
* @author Zaric
* @date 2016-5-29 下午1:25:40
*/
+@Order(-1)
@Component
@Lazy(false)
@Slf4j
@@ -21,7 +26,6 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
private static ApplicationContext applicationContext = null;
-
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
@@ -39,6 +43,27 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
return applicationContext.getBean(requiredType);
}
+ /**
+ * 注册Bean对象
+ * @param beanName beanName
+ * @param bean bean对象
+ * @param 泛型
+ */
+ public static boolean registerBean(String beanName, T bean) {
+ assertContextInjected();
+ boolean ret = false;
+ ConfigurableApplicationContext context = (ConfigurableApplicationContext) applicationContext;
+ if(context != null){
+ try {
+ context.getBeanFactory().registerSingleton(beanName, bean);
+ ret = true;
+ }catch (Exception e){
+ log.error(e.getMessage(), e);
+ }
+ }
+ return ret;
+ }
+
/**
* 清除SpringContextHolder中的ApplicationContext为Null.
*/
@@ -50,12 +75,11 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
}
-
/**
* 检查ApplicationContext不为空.
*/
private static void assertContextInjected() {
- Validate.validState(applicationContext != null, "applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder.");
+ Validate.validState(applicationContext != null, "applicationContext属性未注入.");
}
// ==================
@@ -72,8 +96,9 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
* 实现DisposableBean接口, 在Context关闭时清理静态变量.
*/
@Override
- public void destroy() throws Exception {
+ public void destroy(){
SpringContextHolder.clearHolder();
}
}
+
diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/UserTokenUtil.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/UserTokenUtil.java
index 4a274f9a..4537ce02 100644
--- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/UserTokenUtil.java
+++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/UserTokenUtil.java
@@ -29,6 +29,7 @@ import org.opsli.api.wrapper.system.user.UserModel;
import org.opsli.common.constants.CacheConstants;
import org.opsli.common.constants.SignConstants;
import org.opsli.common.constants.TokenConstants;
+import org.opsli.common.constants.TokenTypeConstants;
import org.opsli.common.exception.ServiceException;
import org.opsli.common.exception.TokenException;
import org.opsli.common.utils.Props;
@@ -116,7 +117,7 @@ public class UserTokenUtil {
);
// 生成 Token 包含 username userId timestamp
- String signToken = JwtUtil.sign(user.getUsername(), user.getId());
+ String signToken = JwtUtil.sign(TokenTypeConstants.TYPE_SYSTEM, user.getUsername(), user.getId());
// 生成MD5 16进制码 用于缩减存储
String signTokenHex = new Md5Hash(signToken).toHex();