feat: 增加用户登录时,从后端服务接口获取帐号、角色等信息
diff --git a/gateway/src/main/java/com/supwisdom/institute/backend/gateway/Application.java b/gateway/src/main/java/com/supwisdom/institute/backend/gateway/Application.java
index f837894..adc1582 100644
--- a/gateway/src/main/java/com/supwisdom/institute/backend/gateway/Application.java
+++ b/gateway/src/main/java/com/supwisdom/institute/backend/gateway/Application.java
@@ -25,12 +25,6 @@
@EnableCustomExceptionHandler
-//@EnableInfrasOnlineDoc
-
-//@EnableInfrasCasSecurity
-
-//@EnableInfrasBasicApi
-
@EnableInfrasJWTWebFluxApi
@EnableInfrasBasicWebFluxApi
public class Application {
diff --git a/gateway/src/main/java/com/supwisdom/institute/backend/gateway/authn/model/Account.java b/gateway/src/main/java/com/supwisdom/institute/backend/gateway/authn/model/Account.java
new file mode 100644
index 0000000..38f38d5
--- /dev/null
+++ b/gateway/src/main/java/com/supwisdom/institute/backend/gateway/authn/model/Account.java
@@ -0,0 +1,70 @@
+package com.supwisdom.institute.backend.gateway.authn.model;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import com.supwisdom.institute.backend.common.framework.model.ABaseModel;
+
+@Getter
+@Setter
+public class Account extends ABaseModel {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -4889952442290543101L;
+
+ private String id;
+
+ /**
+ * 用户名
+ */
+ private String username;
+
+ /**
+ * 密码
+ */
+ private String password;
+
+ /**
+ * 是否可用,1 可用,0 不可用,默认:1
+ */
+ private Boolean enabled;
+ /**
+ * 账号未过期,1 未过期,0 过期,默认:1
+ */
+ private Boolean accountNonExpired;
+ /**
+ * 账号未锁定,1 未锁定,0 锁定,默认:1
+ */
+ private Boolean accountNonLocked;
+ /**
+ * 密码未过期,1 未过期,0 过期,默认:1
+ */
+ private Boolean credentialsNonExpired;
+
+ /**
+ * 姓名
+ */
+ private String name;
+
+ /**
+ * 备注
+ */
+ private String memo;
+
+ /**
+ * 状态(1 启用,0 停用)
+ */
+ private String status;
+
+ /**
+ * 登录手机
+ */
+ private String mobile;
+ /**
+ * 登录邮箱
+ */
+ private String email;
+
+}
diff --git a/gateway/src/main/java/com/supwisdom/institute/backend/gateway/authn/model/Permission.java b/gateway/src/main/java/com/supwisdom/institute/backend/gateway/authn/model/Permission.java
new file mode 100644
index 0000000..0d5c72d
--- /dev/null
+++ b/gateway/src/main/java/com/supwisdom/institute/backend/gateway/authn/model/Permission.java
@@ -0,0 +1,64 @@
+package com.supwisdom.institute.backend.gateway.authn.model;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import com.supwisdom.institute.backend.common.framework.model.ABaseModel;
+
+@Getter
+@Setter
+public class Permission extends ABaseModel {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3042842657207449148L;
+
+ private String id;
+
+ /**
+ * 代码
+ */
+ private String code;
+
+ /**
+ * 名称
+ */
+ private String name;
+
+ /**
+ * 备注
+ */
+ private String memo;
+
+ /**
+ * 状态(1 启用,0 停用)
+ */
+ private String status;
+
+ /**
+ * 类型(1 应用,2 菜单,3 操作)
+ */
+ private String type;
+
+ /**
+ * URL地址
+ */
+ private String url;
+
+ /**
+ * 系统ID
+ */
+ private String applicationId;
+
+ /**
+ * 父级ID
+ */
+ private String parentId;
+
+ /**
+ * 排序
+ */
+ private Integer order;
+
+}
diff --git a/gateway/src/main/java/com/supwisdom/institute/backend/gateway/authn/model/Role.java b/gateway/src/main/java/com/supwisdom/institute/backend/gateway/authn/model/Role.java
new file mode 100644
index 0000000..034ff84
--- /dev/null
+++ b/gateway/src/main/java/com/supwisdom/institute/backend/gateway/authn/model/Role.java
@@ -0,0 +1,39 @@
+package com.supwisdom.institute.backend.gateway.authn.model;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import com.supwisdom.institute.backend.common.framework.model.ABaseModel;
+
+@Getter
+@Setter
+public class Role extends ABaseModel {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -8551951601186240995L;
+
+ private String id;
+
+ /**
+ * 代码
+ */
+ private String code;
+
+ /**
+ * 名称
+ */
+ private String name;
+
+ /**
+ * 备注
+ */
+ private String memo;
+
+ /**
+ * 状态(1 启用,0 停用)
+ */
+ private String status;
+
+}
diff --git a/gateway/src/main/java/com/supwisdom/institute/backend/gateway/authn/remote/configuration/AuthnAccountRestTemplateConfig.java b/gateway/src/main/java/com/supwisdom/institute/backend/gateway/authn/remote/configuration/AuthnAccountRestTemplateConfig.java
new file mode 100644
index 0000000..5e98c4a
--- /dev/null
+++ b/gateway/src/main/java/com/supwisdom/institute/backend/gateway/authn/remote/configuration/AuthnAccountRestTemplateConfig.java
@@ -0,0 +1,92 @@
+package com.supwisdom.institute.backend.gateway.authn.remote.configuration;
+
+import javax.net.ssl.SSLContext;
+
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.apache.http.ssl.SSLContexts;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.client.ClientHttpRequestFactory;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.http.client.SimpleClientHttpRequestFactory;
+import org.springframework.util.ResourceUtils;
+import org.springframework.web.client.RestTemplate;
+
+@Configuration
+public class AuthnAccountRestTemplateConfig {
+
+ @Bean
+ public ClientHttpRequestFactory simpleClientHttpRequestFactory(
+ @Value("${sw-backend-base-api.client-auth.enabled:false}") boolean enabled,
+ @Value("${sw-backend-base-api.client-auth.key-password:}") String keyPassword,
+ @Value("${sw-backend-base-api.client-auth.key-store:}") String keyStore,
+ @Value("${sw-backend-base-api.client-auth.key-store-password:}") String keyStorePassword,
+ @Value("${sw-backend-base-api.client-auth.trust-store:}") String trustStore,
+ @Value("${sw-backend-base-api.client-auth.trust-store-password:}") String trustStorePassword
+ ) {
+ if (!enabled) {
+ SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
+ factory.setReadTimeout(5000);// 单位为ms
+ factory.setConnectTimeout(5000);// 单位为ms
+ return factory;
+ }
+
+ if (keyStore == null || keyStore.isEmpty()) {
+ SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
+ factory.setReadTimeout(5000);// 单位为ms
+ factory.setConnectTimeout(5000);// 单位为ms
+ return factory;
+ } else {
+ try {
+ SSLContextBuilder sslContextBuilder = SSLContexts.custom();
+ if (trustStore == null || trustStore.isEmpty()) {
+ } else {
+ sslContextBuilder
+// .loadTrustMaterial(TrustAllStrategy.INSTANCE)
+ .loadTrustMaterial(
+ ResourceUtils.getFile(trustStore),
+ trustStorePassword.toCharArray()
+ );
+ }
+
+ sslContextBuilder
+ .loadKeyMaterial(
+ ResourceUtils.getFile(keyStore),
+ keyStorePassword.toCharArray(),
+ keyPassword.toCharArray());
+
+ SSLContext sslContext = sslContextBuilder.build();
+
+ SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
+ sslContext,
+ SSLConnectionSocketFactory.getDefaultHostnameVerifier());
+
+ CloseableHttpClient httpClient = HttpClients.custom()
+ .setSSLSocketFactory(sslsf)
+ .build();
+
+ HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
+ factory.setReadTimeout(5000);// 单位为ms
+ factory.setConnectTimeout(5000);// 单位为ms
+ return factory;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
+ factory.setReadTimeout(5000);// 单位为ms
+ factory.setConnectTimeout(5000);// 单位为ms
+ return factory;
+ }
+
+ @Bean(name = "authnAccountRestTemplate")
+ public RestTemplate authnAccountRestTemplate(ClientHttpRequestFactory requestFactory) {
+ return new RestTemplate(requestFactory);
+ }
+
+}
diff --git a/gateway/src/main/java/com/supwisdom/institute/backend/gateway/authn/remote/web/client/AuthnAccountRemoteRestTemplate.java b/gateway/src/main/java/com/supwisdom/institute/backend/gateway/authn/remote/web/client/AuthnAccountRemoteRestTemplate.java
new file mode 100644
index 0000000..65cf89f
--- /dev/null
+++ b/gateway/src/main/java/com/supwisdom/institute/backend/gateway/authn/remote/web/client/AuthnAccountRemoteRestTemplate.java
@@ -0,0 +1,123 @@
+package com.supwisdom.institute.backend.gateway.authn.remote.web.client;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestTemplate;
+
+import com.alibaba.fastjson.JSONObject;
+
+@Slf4j
+@Component
+public class AuthnAccountRemoteRestTemplate {
+
+ @Autowired
+ private RestTemplate authnAccountRestTemplate;
+
+ @Value(value = "${sw-backend-base-api.uri}/v1/authn")
+ private String url;
+
+ private JSONObject defaultErrorJson(Throwable cause) {
+ JSONObject error = new JSONObject();
+
+ error.put("code", -1);
+ error.put("message", cause.getMessage());
+ error.put("error", cause.getMessage());
+
+ return error;
+ }
+
+ public JSONObject account(String username) {
+
+ try {
+ final String path = "/{username}/account";
+ final String url = this.url + StringUtils.replaceEach(path, new String[] {"{username}"}, new String[] {username});
+ log.debug(url);
+
+ return authnAccountRestTemplate.getForObject(this.url + path, JSONObject.class);
+ } catch (Exception e) {
+ e.printStackTrace();
+
+ return defaultErrorJson(e);
+ }
+ }
+
+ public JSONObject roles(String username) {
+
+ try {
+ final String path = "/{username}/roles";
+ final String url = this.url + StringUtils.replaceEach(path, new String[] {"{username}"}, new String[] {username});
+ log.debug(url);
+
+ return authnAccountRestTemplate.getForObject(url, JSONObject.class);
+ } catch (Exception e) {
+ e.printStackTrace();
+
+ return defaultErrorJson(e);
+ }
+ }
+
+ public JSONObject applications(String username, String applicationId) {
+
+ try {
+ final String path = "/{username}/applications";
+ final String url = this.url + StringUtils.replaceEach(path, new String[] {"{username}"}, new String[] {username});
+ log.debug(url);
+
+ return authnAccountRestTemplate.getForObject(this.url + path, JSONObject.class);
+ } catch (Exception e) {
+ e.printStackTrace();
+
+ return defaultErrorJson(e);
+ }
+ }
+
+ public JSONObject menus(String username, String applicationId) {
+
+ try {
+ final String path = "/{username}/menus";
+ final String url = this.url + StringUtils.replaceEach(path, new String[] {"{username}"}, new String[] {username});
+ log.debug(url);
+
+ return authnAccountRestTemplate.getForObject(this.url + path, JSONObject.class);
+ } catch (Exception e) {
+ e.printStackTrace();
+
+ return defaultErrorJson(e);
+ }
+ }
+
+ public JSONObject operations(String username, String applicationId) {
+
+ try {
+ final String path = "/{username}/operations";
+ final String url = this.url + StringUtils.replaceEach(path, new String[] {"{username}"}, new String[] {username});
+ log.debug(url);
+
+ return authnAccountRestTemplate.getForObject(this.url + path, JSONObject.class);
+ } catch (Exception e) {
+ e.printStackTrace();
+
+ return defaultErrorJson(e);
+ }
+ }
+
+ public JSONObject resources(String username, String applicationId) {
+
+ try {
+ final String path = "/{username}/resources";
+ final String url = this.url + StringUtils.replaceEach(path, new String[] {"{username}"}, new String[] {username});
+ log.debug(url);
+
+ return authnAccountRestTemplate.getForObject(this.url + path, JSONObject.class);
+ } catch (Exception e) {
+ e.printStackTrace();
+
+ return defaultErrorJson(e);
+ }
+ }
+
+}
diff --git a/gateway/src/main/java/com/supwisdom/institute/backend/gateway/authn/service/AuthnAccountService.java b/gateway/src/main/java/com/supwisdom/institute/backend/gateway/authn/service/AuthnAccountService.java
new file mode 100644
index 0000000..beeb74a
--- /dev/null
+++ b/gateway/src/main/java/com/supwisdom/institute/backend/gateway/authn/service/AuthnAccountService.java
@@ -0,0 +1,71 @@
+package com.supwisdom.institute.backend.gateway.authn.service;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.supwisdom.institute.backend.gateway.authn.model.Account;
+import com.supwisdom.institute.backend.gateway.authn.model.Permission;
+import com.supwisdom.institute.backend.gateway.authn.model.Role;
+import com.supwisdom.institute.backend.gateway.authn.remote.web.client.AuthnAccountRemoteRestTemplate;
+
+@Service
+public class AuthnAccountService {
+
+// @Autowired
+// private AuthnAccountRemoteFeignClient authnAccountRemote;
+
+ @Autowired
+ private AuthnAccountRemoteRestTemplate authnAccountRemote;
+
+ public Account account(String username) {
+
+ JSONObject jsonObject = authnAccountRemote.account(username);
+ if (jsonObject == null) {
+ return null;
+ }
+
+ if (jsonObject.getIntValue("code") == 0) {
+ JSONObject data = jsonObject.getJSONObject("data");
+
+ return data.toJavaObject(Account.class);
+ }
+
+ return null;
+ }
+
+ public List<Role> roles(String username) {
+
+ JSONObject jsonObject = authnAccountRemote.roles(username);
+ if (jsonObject == null) {
+ return null;
+ }
+
+ if (jsonObject.getIntValue("code") == 0) {
+ JSONObject data = jsonObject.getJSONObject("data");
+
+ return data.getJSONArray("roles").toJavaList(Role.class);
+ }
+
+ return null;
+ }
+
+ public List<Permission> menus(String username, String applicationId) {
+
+ JSONObject jsonObject = authnAccountRemote.menus(username, applicationId);
+ if (jsonObject == null) {
+ return null;
+ }
+
+ if (jsonObject.getIntValue("code") == 0) {
+ JSONObject data = jsonObject.getJSONObject("data");
+
+ return data.getJSONArray("permissions").toJavaList(Permission.class);
+ }
+
+ return null;
+ }
+
+}
diff --git a/gateway/src/main/java/com/supwisdom/institute/backend/gateway/configuration/UserDetailsServiceConfig.java b/gateway/src/main/java/com/supwisdom/institute/backend/gateway/configuration/UserDetailsServiceConfig.java
index cafbc17..6f8be84 100644
--- a/gateway/src/main/java/com/supwisdom/institute/backend/gateway/configuration/UserDetailsServiceConfig.java
+++ b/gateway/src/main/java/com/supwisdom/institute/backend/gateway/configuration/UserDetailsServiceConfig.java
@@ -12,20 +12,20 @@
@Configuration
public class UserDetailsServiceConfig {
-// @Bean
-// public MyUserDetailsService userDetailsService() throws Exception {
-// MyUserDetailsService myUserDetailsService = new MyUserDetailsService();
-// log.debug("UserDetailsServiceConfig myUserDetailsService is {}", myUserDetailsService);
-//
-// return myUserDetailsService;
-// }
-
@Bean
- public InMemeryUserDetailsService userDetailsService() throws Exception {
- InMemeryUserDetailsService inMemeryUserDetailsService = new InMemeryUserDetailsService();
- log.debug("UserDetailsServiceConfig inMemeryUserDetailsService is {}", inMemeryUserDetailsService);
+ public MyUserDetailsService userDetailsService() throws Exception {
+ MyUserDetailsService myUserDetailsService = new MyUserDetailsService();
+ log.debug("UserDetailsServiceConfig myUserDetailsService is {}", myUserDetailsService);
- return inMemeryUserDetailsService;
+ return myUserDetailsService;
}
+// @Bean
+// public InMemeryUserDetailsService userDetailsService() throws Exception {
+// InMemeryUserDetailsService inMemeryUserDetailsService = new InMemeryUserDetailsService();
+// log.debug("UserDetailsServiceConfig inMemeryUserDetailsService is {}", inMemeryUserDetailsService);
+//
+// return inMemeryUserDetailsService;
+// }
+
}
diff --git a/gateway/src/main/java/com/supwisdom/institute/backend/gateway/security/core/userdetails/MyUserDetailsService.java b/gateway/src/main/java/com/supwisdom/institute/backend/gateway/security/core/userdetails/MyUserDetailsService.java
index e5bfec8..171f2cf 100644
--- a/gateway/src/main/java/com/supwisdom/institute/backend/gateway/security/core/userdetails/MyUserDetailsService.java
+++ b/gateway/src/main/java/com/supwisdom/institute/backend/gateway/security/core/userdetails/MyUserDetailsService.java
@@ -15,6 +15,10 @@
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
+import com.supwisdom.institute.backend.gateway.authn.model.Account;
+import com.supwisdom.institute.backend.gateway.authn.model.Role;
+import com.supwisdom.institute.backend.gateway.authn.service.AuthnAccountService;
+
import reactor.core.publisher.Mono;
import lombok.extern.slf4j.Slf4j;
@@ -24,46 +28,16 @@
@Autowired
PasswordEncoder passwordEncoder;
-// @Autowired
-// AccountService accountService;
+ @Autowired
+ AuthnAccountService authnAccountService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // TODO:
log.debug("MyUserDetailsService.loadUserByUsername({})", username);
-// Account account = accountService.loadByUsername(username);
-// if (account == null) {
-// throw new UsernameNotFoundException(String.format("%s not found", username));
-// }
-//
-// List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
-//// for (Role role : securityUser.getRoles()) {
-//// authorities.add(new SimpleGrantedAuthority(role.getCode()));
-//// }
-// // FIXME:
-// authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
-// authorities.add(new SimpleGrantedAuthority("administrator"));
-// authorities.add(new SimpleGrantedAuthority("user"));
-//
-// Map<String, Object> attributes = new HashMap<String, Object>();
-// attributes.put("userId", account.getUser().getId());
-// attributes.put("userUid", account.getUser().getUid());
-//
-// MyUser myUser = new MyUser(
-// account.getAccountName(),
-// account.getUser().getPassWord(),
-// account.getActivation() && "Normal".equals(account.getState()) ? true : false,
-// account.getAccountExpiryDate() == null || Calendar.getInstance().getTime().before(account.getAccountExpiryDate()) ? true : false,
-// true,
-// true,
-// authorities,
-// attributes);
-//
-// log.debug("myUser is {}", myUser);
-
- MyUser myUser = null;
-
+ MyUser myUser = loadUser(username);
+
return myUser;
}
@@ -71,9 +45,37 @@
public Mono<UserDetails> findByUsername(String username) {
log.debug("MyUserDetailsService.findByUsername({})", username);
- MyUser myUser = null;
-
+ MyUser myUser = loadUser(username);
+
return Mono.just(myUser);
}
+
+ private MyUser loadUser(String username) {
+
+ Account account = authnAccountService.account(username);
+ if (account == null) {
+ throw new UsernameNotFoundException(String.format("%s not found", username));
+ }
+
+ List<Role> roles = authnAccountService.roles(username);
+
+ List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
+ for (Role role : roles) {
+ authorities.add(new SimpleGrantedAuthority(role.getCode()));
+ }
+
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put("accountId", account.getId());
+ attributes.put("accountName", account.getName());
+ //attributes.put("accountMobile", account.getMobile());
+ //attributes.put("accountEmail", account.getEmail());
+
+ MyUser myUser = new MyUser(account.getUsername(), passwordEncoder.encode(account.getPassword()),
+ account.getEnabled(), account.getAccountNonExpired(), account.getCredentialsNonExpired(), account.getAccountNonLocked(),
+ authorities, attributes);
+ log.debug("myUser is {}", myUser);
+
+ return myUser;
+ }
}
diff --git a/gateway/src/main/resources/application-docker.yml b/gateway/src/main/resources/application-docker.yml
index b5ea861..219f4f7 100644
--- a/gateway/src/main/resources/application-docker.yml
+++ b/gateway/src/main/resources/application-docker.yml
@@ -103,3 +103,15 @@
#CAS服务地址
cas.server.host.url: ${CAS_SERVER_HOST_URL:https://cas-server/cas}
+
+
+sw-backend-base-api:
+ uri: ${SW_BACKEND_BASE_API_URI:https://sw-backend-admin-sa}
+ client-auth:
+ enabled: ${SW_BACKEND_BASE_API_CLIENT_AUTH_ENABLED:true}
+ key-password: ${SW_BACKEND_BASE_API_CLIENT_AUTH_KEY_PASSWORD:}
+ key-store: ${SW_BACKEND_BASE_API_CLIENT_AUTH_KEYSTORE_FILE:file:/certs/common/common.keystore}
+ key-store-password: ${SW_BACKEND_BASE_API_CLIENT_AUTH_KEYSTORE_PASSWORD:}
+ trust-store: ${SW_BACKEND_BASE_API_CLIENT_AUTH_TRUSTSTORE_FILE:file:/certs/common/common.truststore}
+ trust-store-password: ${SW_BACKEND_BASE_API_CLIENT_AUTH_TRUSTSTORE_PASSWORD:}
+
\ No newline at end of file
diff --git a/gateway/src/main/resources/application.yml b/gateway/src/main/resources/application.yml
index 7e88467..c72cbc7 100644
--- a/gateway/src/main/resources/application.yml
+++ b/gateway/src/main/resources/application.yml
@@ -94,3 +94,7 @@
#CAS服务地址
cas.server.host.url: https://cas.supwisdom.com/cas
+
+
+sw-backend-base-api:
+ uri: http://localhost:8082