完善授权控制代码
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