完善授权控制代码
diff --git a/samples/client/src/main/java/com/supwisdom/leaveschool/client/config/InfrasFilterSecurityInterceptorConfig.java b/samples/client/src/main/java/com/supwisdom/leaveschool/client/config/InfrasFilterSecurityInterceptorConfig.java
new file mode 100644
index 0000000..7f8ed14
--- /dev/null
+++ b/samples/client/src/main/java/com/supwisdom/leaveschool/client/config/InfrasFilterSecurityInterceptorConfig.java
@@ -0,0 +1,44 @@
+package com.supwisdom.leaveschool.client.config;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.access.AccessDecisionManager;
+import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
+
+import com.supwisdom.infras.security.web.access.intercept.InfrasFilterSecurityInterceptor;
+import com.supwisdom.leaveschool.client.security.web.access.MyAccessDecisionManager;
+import com.supwisdom.leaveschool.client.security.web.access.intercept.MyFilterInvocationSecurityMetadataSource;
+import com.supwisdom.leaveschool.client.security.web.access.intercept.MyFilterSecurityInterceptor;
+
+@Configuration
+public class InfrasFilterSecurityInterceptorConfig {
+
+ private static final Logger logger = LoggerFactory.getLogger(InfrasFilterSecurityInterceptorConfig.class);
+
+ @Bean
+ public FilterInvocationSecurityMetadataSource securityMetadataSource() {
+ MyFilterInvocationSecurityMetadataSource securityMetadataSource = new MyFilterInvocationSecurityMetadataSource();
+ logger.debug("InfrasFilterSecurityInterceptorConfig securityMetadataSource is {}", securityMetadataSource);
+
+ return securityMetadataSource;
+ }
+
+ @Bean
+ public AccessDecisionManager accessDecisionManager() {
+ MyAccessDecisionManager accessDecisionManager = new MyAccessDecisionManager();
+ logger.debug("InfrasFilterSecurityInterceptorConfig accessDecisionManager is {}", accessDecisionManager);
+
+ return accessDecisionManager;
+ }
+
+ @Bean
+ public InfrasFilterSecurityInterceptor infrasFilterSecurityInterceptor() throws Exception {
+ MyFilterSecurityInterceptor myFilterSecurityInterceptor = new MyFilterSecurityInterceptor();
+ logger.debug("InfrasFilterSecurityInterceptorConfig infrasFilterSecurityInterceptor is {}", myFilterSecurityInterceptor);
+
+ return myFilterSecurityInterceptor;
+ }
+
+}
diff --git a/samples/client/src/main/java/com/supwisdom/leaveschool/client/config/PasswordEncoderConfig.java b/samples/client/src/main/java/com/supwisdom/leaveschool/client/config/PasswordEncoderConfig.java
index 1fef80d..4957c3c 100644
--- a/samples/client/src/main/java/com/supwisdom/leaveschool/client/config/PasswordEncoderConfig.java
+++ b/samples/client/src/main/java/com/supwisdom/leaveschool/client/config/PasswordEncoderConfig.java
@@ -9,6 +9,7 @@
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
+@SuppressWarnings("deprecation")
@Configuration
public class PasswordEncoderConfig {
diff --git a/samples/client/src/main/java/com/supwisdom/leaveschool/client/config/UserDetailsServiceConfig.java b/samples/client/src/main/java/com/supwisdom/leaveschool/client/config/UserDetailsServiceConfig.java
index 25253e3..fa934de 100644
--- a/samples/client/src/main/java/com/supwisdom/leaveschool/client/config/UserDetailsServiceConfig.java
+++ b/samples/client/src/main/java/com/supwisdom/leaveschool/client/config/UserDetailsServiceConfig.java
@@ -6,6 +6,7 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.userdetails.UserDetailsService;
+import com.supwisdom.leaveschool.client.security.core.userdetails.InMemeryUserDetailsService;
import com.supwisdom.leaveschool.client.security.core.userdetails.MyUserDetailsService;
@Configuration
@@ -14,10 +15,19 @@
private static final Logger logger = LoggerFactory.getLogger(UserDetailsServiceConfig.class);
@Bean
- public UserDetailsService userDetailsService(MyUserDetailsService myUserDetailsService) throws Exception {
-
- logger.debug("UserDetailsServiceConfig userDetailsService is {}", myUserDetailsService);
+ public UserDetailsService userDetailsService() throws Exception {
+ MyUserDetailsService myUserDetailsService = new MyUserDetailsService();
+ logger.debug("UserDetailsServiceConfig myUserDetailsService is {}", myUserDetailsService);
+
return myUserDetailsService;
}
-
+
+// @Bean
+// public UserDetailsService userDetailsService() throws Exception {
+// InMemeryUserDetailsService inMemeryUserDetailsService = new InMemeryUserDetailsService();
+// logger.debug("UserDetailsServiceConfig inMemeryUserDetailsService is {}", inMemeryUserDetailsService);
+//
+// return inMemeryUserDetailsService;
+// }
+
}
diff --git a/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/core/userdetails/InMemeryUserDetailsService.java b/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/core/userdetails/InMemeryUserDetailsService.java
new file mode 100644
index 0000000..cf62a89
--- /dev/null
+++ b/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/core/userdetails/InMemeryUserDetailsService.java
@@ -0,0 +1,38 @@
+package com.supwisdom.leaveschool.client.security.core.userdetails;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+public class InMemeryUserDetailsService implements UserDetailsService {
+
+ private static final Logger logger = LoggerFactory.getLogger(InMemeryUserDetailsService.class);
+
+ @Autowired
+ PasswordEncoder passwordEncoder;
+
+ @Override
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+
+ logger.debug("InMemeryUserDetailsService.loadUserByUsername({})", username);
+
+ List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
+ authorities.add(new SimpleGrantedAuthority("administrator"));
+ authorities.add(new SimpleGrantedAuthority("user"));
+
+ MyUser myUser = new MyUser("user", passwordEncoder.encode("password"), authorities);
+ logger.debug("myUser is {}", myUser);
+
+ return myUser;
+ }
+
+}
diff --git a/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/core/userdetails/MyUserDetailsService.java b/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/core/userdetails/MyUserDetailsService.java
index 83ee8ab..be7c59f 100644
--- a/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/core/userdetails/MyUserDetailsService.java
+++ b/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/core/userdetails/MyUserDetailsService.java
@@ -12,12 +12,11 @@
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
-import org.springframework.stereotype.Service;
import com.supwisdom.leaveschool.client.service.SampleUser1SecurityUserRemoteService;
+import com.supwisdom.leaveschool.proxy.user.domain.Role;
import com.supwisdom.leaveschool.proxy.user.model.SecurityUser;
-@Service
public class MyUserDetailsService implements UserDetailsService {
private static final Logger logger = LoggerFactory.getLogger(MyUserDetailsService.class);
@@ -40,7 +39,9 @@
// TODO: 从数据库获取
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
- authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
+ for (Role role : securityUser.getRoles()) {
+ authorities.add(new SimpleGrantedAuthority(role.getCode()));
+ }
MyUser myUser = new MyUser(securityUser.getUser().getUsername(), securityUser.getUser().getPassword(), authorities);
logger.debug("myUser is {}", myUser);
diff --git a/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/web/access/MyAccessDecisionManager.java b/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/web/access/MyAccessDecisionManager.java
new file mode 100644
index 0000000..003410a
--- /dev/null
+++ b/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/web/access/MyAccessDecisionManager.java
@@ -0,0 +1,48 @@
+package com.supwisdom.leaveschool.client.security.web.access;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.springframework.security.access.AccessDecisionManager;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.authentication.InsufficientAuthenticationException;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+
+public class MyAccessDecisionManager implements AccessDecisionManager {
+
+ @Override
+ public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
+ throws AccessDeniedException, InsufficientAuthenticationException {
+
+ if (null == configAttributes || configAttributes.size() <= 0) {
+ return;
+ }
+
+ ConfigAttribute ca;
+ String needRole;
+ for (Iterator<ConfigAttribute> iter = configAttributes.iterator(); iter.hasNext();) {
+ ca = iter.next();
+ needRole = ca.getAttribute();
+ for (GrantedAuthority ga : authentication.getAuthorities()) { // authentication 为在注释1 中循环添加到 GrantedAuthority 对象中的权限信息集合
+ if (needRole.trim().equals(ga.getAuthority())) {
+ return;
+ }
+ }
+ }
+
+ throw new AccessDeniedException("no right");
+ }
+
+ @Override
+ public boolean supports(ConfigAttribute attribute) {
+ return true;
+ }
+
+ @Override
+ public boolean supports(Class<?> clazz) {
+ return true;
+ }
+
+}
diff --git a/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/web/access/intercept/MyFilterInvocationSecurityMetadataSource.java b/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/web/access/intercept/MyFilterInvocationSecurityMetadataSource.java
new file mode 100644
index 0000000..5b21eec
--- /dev/null
+++ b/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/web/access/intercept/MyFilterInvocationSecurityMetadataSource.java
@@ -0,0 +1,42 @@
+package com.supwisdom.leaveschool.client.security.web.access.intercept;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.access.SecurityConfig;
+import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
+
+public class MyFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
+
+ /**
+ * 获取当前请求关联的所有角色code {@link SecurityConfig}
+ * 用于和用户拥有的角色code 进行比对
+ */
+ @Override
+ public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
+
+ HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
+
+ Collection<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>(); // FIXME: 返回当前请求的url 对应的 角色代码
+ attributes.add(new SecurityConfig("administrator"));
+
+ return attributes;
+ }
+
+ @Override
+ public Collection<ConfigAttribute> getAllConfigAttributes() {
+
+ return null;
+ }
+
+ @Override
+ public boolean supports(Class<?> clazz) {
+
+ return true;
+ }
+
+}
diff --git a/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/web/access/intercept/MyFilterSecurityInterceptor.java b/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/web/access/intercept/MyFilterSecurityInterceptor.java
new file mode 100644
index 0000000..ceca250
--- /dev/null
+++ b/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/web/access/intercept/MyFilterSecurityInterceptor.java
@@ -0,0 +1,82 @@
+package com.supwisdom.leaveschool.client.security.web.access.intercept;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.servlet.ServletException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.AccessDecisionManager;
+import org.springframework.security.access.SecurityMetadataSource;
+import org.springframework.security.access.intercept.InterceptorStatusToken;
+//import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
+
+import com.supwisdom.infras.security.web.access.intercept.InfrasFilterSecurityInterceptor;
+
+public class MyFilterSecurityInterceptor extends InfrasFilterSecurityInterceptor {
+
+ private static final Logger logger = LoggerFactory.getLogger(MyFilterSecurityInterceptor.class);
+
+ @Autowired
+ private FilterInvocationSecurityMetadataSource securityMetadataSource;
+
+ @Autowired
+ public void setAccessDecisionManager(AccessDecisionManager accessDecisionManager) {
+
+ super.setAccessDecisionManager(accessDecisionManager);
+ }
+
+// @Autowired
+// public void setAuthenticationManager(AuthenticationManager newManager) {
+//
+// super.setAuthenticationManager(newManager);
+// };
+
+ @Override
+ public void invoke(FilterInvocation fi) throws IOException, ServletException {
+
+ Set<String> noneSecurityUrl = new HashSet<String>();
+ noneSecurityUrl.add("/");
+ noneSecurityUrl.add("/index");
+ noneSecurityUrl.add("/web/index");
+ noneSecurityUrl.add("/web/login");
+ noneSecurityUrl.add("/web/logout");
+
+ if (fi.getRequest() != null) {
+ String requestUrl = fi.getRequestUrl(); logger.debug("MyFilterSecurityInterceptor invoke requestUrl: {}", requestUrl);
+ if (noneSecurityUrl.contains(requestUrl)) {
+ fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
+ return;
+ }
+ }
+
+ // fi里面有一个被拦截的url
+ // 里面调用MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限
+ // 再调用MyAccessDecisionManager的decide方法来校验用户的权限是否足够
+ InterceptorStatusToken token = super.beforeInvocation(fi);
+ try {
+ // 执行下一个拦截器
+ fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
+ } finally {
+ super.afterInvocation(token, null);
+ }
+ }
+
+ @Override
+ public Class<?> getSecureObjectClass() {
+
+ return FilterInvocation.class;
+ }
+
+ @Override
+ public SecurityMetadataSource obtainSecurityMetadataSource() {
+
+ return this.securityMetadataSource;
+ }
+
+}
diff --git a/samples/client/src/main/resources/application.yml b/samples/client/src/main/resources/application.yml
index 0141d8e..ad1efe4 100755
--- a/samples/client/src/main/resources/application.yml
+++ b/samples/client/src/main/resources/application.yml
@@ -36,7 +36,25 @@
thread:
timeoutInMilliseconds: 12000
+#infras.security.cas.enabled: true
+
+## CAS
+#应用访问地址
+app.server.host.url: http://localhost:8080
+#应用登录地址
+app.login.url: /web/caslogin
+#应用登出地址
+app.logout.url: /web/logout
+
+#CAS服务地址
+cas.server.host.url: http://101.231.81.202:9080/cas
+#CAS服务登录地址
+cas.server.host.login_url: ${cas.server.host.url}/login
+#CAS服务登出地址
+cas.server.host.logout_url: ${cas.server.host.url}/logout?service=${app.server.host.url}
+
+
gateway.api.url: http://localhost:5555
-#sample-user.api.url: http://localhost:5555/sample-user
+#sample-user.api.url: ${gateway.api.url}/sample-user
sample-user.api.url: http://localhost:10010