Quantcast
Channel: IT瘾博客推荐
Viewing all articles
Browse latest Browse all 532

Spring Boot 使用Spring security 集成CAS - CSDN博客

$
0
0

1.创建工程

      创建Maven工程:springboot-security-cas

2.加入依赖

      创建工程后,打开pom.xml,在pom.xml中加入以下内容:
[html]  view plain  copy
  1. <parent>  
  2.         <groupId>org.springframework.boot</groupId>  
  3.         <artifactId>spring-boot-starter-parent</artifactId>  
  4.         <version>1.4.3.RELEASE</version>  
  5.     </parent>  
  6.     <properties>  
  7.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  8.         <java.version>1.8</java.version>  
  9.     </properties>  
  10.     <dependencies>  
  11.         <dependency>  
  12.             <groupId>org.springframework.boot</groupId>  
  13.             <artifactId>spring-boot-starter</artifactId>  
  14.         </dependency>  
  15.         <dependency>  
  16.             <groupId>org.springframework.boot</groupId>  
  17.             <artifactId>spring-boot-starter-web</artifactId>  
  18.         </dependency>  
  19.         <!-- security starter Poms -->  
  20.         <dependency>  
  21.             <groupId>org.springframework.boot</groupId>  
  22.             <artifactId>spring-boot-starter-security</artifactId>  
  23.         </dependency>  
  24.         <!-- security 对CAS支持 -->  
  25.         <dependency>  
  26.             <groupId>org.springframework.security</groupId>  
  27.             <artifactId>spring-security-cas</artifactId>  
  28.         </dependency>  
  29.         <!-- security taglibs -->  
  30.         <dependency>  
  31.             <groupId>org.springframework.security</groupId>  
  32.             <artifactId>spring-security-taglibs</artifactId>  
  33.         </dependency>  
  34.         <!-- 热加载 -->  
  35.         <dependency>  
  36.             <groupId>org.springframework.boot</groupId>  
  37.             <artifactId>spring-boot-devtools</artifactId>  
  38.             <optional>true</optional>  
  39.         </dependency>  
  40.         <dependency>  
  41.             <groupId>org.springframework.boot</groupId>  
  42.             <artifactId>spring-boot-configuration-processor</artifactId>  
  43.             <optional>true</optional>  
  44.         </dependency>  
  45.     </dependencies>  
  46.     <build>  
  47.         <plugins>  
  48.             <plugin>  
  49.                 <groupId>org.springframework.boot</groupId>  
  50.                 <artifactId>spring-boot-maven-plugin</artifactId>  
  51.             </plugin>  
  52.         </plugins>  
  53.     </build>  

3.创建application.properties

      创建application.properties文件,加入以下内容:
[plain]  view plain  copy
  1. #CAS服务地址  
  2. cas.server.host.url=http://localhost:8081/cas  
  3. #CAS服务登录地址  
  4. cas.server.host.login_url=${cas.server.host.url}/login  
  5. #CAS服务登出地址  
  6. cas.server.host.logout_url=${cas.server.host.url}/logout?service=${app.server.host.url}  
  7. #应用访问地址  
  8. app.server.host.url=http://localhost:8080  
  9. #应用登录地址  
  10. app.login.url=/login  
  11. #应用登出地址  
  12. app.logout.url=/logout  

4.创建入口启动类(MainConfig)

      创建入口启动类MainConfig,完整代码如下:
[java]  view plain  copy
  1. package com.chengli.springboot;  
  2.   
  3. import org.springframework.boot.SpringApplication;  
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;  
  5. import org.springframework.security.access.prepost.PreAuthorize;  
  6. import org.springframework.web.bind.annotation.RequestMapping;  
  7. import org.springframework.web.bind.annotation.RestController;  
  8.   
  9. @RestController  
  10. @SpringBootApplication  
  11. public class MainConfig {  
  12.     public static void main(String[] args) {  
  13.         SpringApplication.run(MainConfig.class, args);  
  14.     }  
  15.   
  16.     @RequestMapping("/")  
  17.     public String index() {  
  18.         return "访问了首页哦";  
  19.     }  
  20.   
  21.     @RequestMapping("/hello")  
  22.     public String hello() {  
  23.         return "不验证哦";  
  24.     }  
  25.   
  26.     @PreAuthorize("hasAuthority('TEST')")//有TEST权限的才能访问  
  27.     @RequestMapping("/security")  
  28.     public String security() {  
  29.         return "hello world security";  
  30.     }  
  31.   
  32.     @PreAuthorize("hasAuthority('ADMIN')")//必须要有ADMIN权限的才能访问  
  33.     @RequestMapping("/authorize")  
  34.     public String authorize() {  
  35.         return "有权限访问";  
  36.     }  
  37.       
  38.     /**这里注意的是,TEST与ADMIN只是权限编码,可以自己定义一套规则,根据实际情况即可*/  
  39. }  

5.创建Security配置类(SecurityConfig)

      创建Security配置类SecurityConfig,完整代码如下:
[java]  view plain  copy
  1. package com.chengli.springboot.security;  
  2.   
  3. import org.jasig.cas.client.session.SingleSignOutFilter;  
  4. import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;  
  5. import org.springframework.beans.factory.annotation.Autowired;  
  6. import org.springframework.context.annotation.Bean;  
  7. import org.springframework.context.annotation.Configuration;  
  8. import org.springframework.security.cas.ServiceProperties;  
  9. import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;  
  10. import org.springframework.security.cas.authentication.CasAuthenticationProvider;  
  11. import org.springframework.security.cas.web.CasAuthenticationEntryPoint;  
  12. import org.springframework.security.cas.web.CasAuthenticationFilter;  
  13. import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;  
  14. import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;  
  15. import org.springframework.security.config.annotation.web.builders.HttpSecurity;  
  16. import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;  
  17. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;  
  18. import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;  
  19. import org.springframework.security.web.authentication.logout.LogoutFilter;  
  20. import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;  
  21.   
  22. import com.chengli.springboot.custom.CustomUserDetailsService;  
  23. import com.chengli.springboot.properties.CasProperties;  
  24.   
  25. @Configuration  
  26. @EnableWebSecurity //启用web权限  
  27. @EnableGlobalMethodSecurity(prePostEnabled = true) //启用方法验证  
  28. public class SecurityConfig extends WebSecurityConfigurerAdapter {  
  29.     @Autowired  
  30.     private CasProperties casProperties;  
  31.       
  32.     /**定义认证用户信息获取来源,密码校验规则等*/  
  33.     @Override  
  34.     protected void configure(AuthenticationManagerBuilder auth) throws Exception {  
  35.         super.configure(auth);  
  36.         auth.authenticationProvider(casAuthenticationProvider());  
  37.         //inMemoryAuthentication 从内存中获取  
  38.         //auth.inMemoryAuthentication().withUser("chengli").password("123456").roles("USER")  
  39.         //.and().withUser("admin").password("123456").roles("ADMIN");  
  40.           
  41.         //jdbcAuthentication从数据库中获取,但是默认是以security提供的表结构  
  42.         //usersByUsernameQuery 指定查询用户SQL  
  43.         //authoritiesByUsernameQuery 指定查询权限SQL  
  44.         //auth.jdbcAuthentication().dataSource(dataSource).usersByUsernameQuery(query).authoritiesByUsernameQuery(query);  
  45.           
  46.         //注入userDetailsService,需要实现userDetailsService接口  
  47.         //auth.userDetailsService(userDetailsService);  
  48.     }  
  49.       
  50.     /**定义安全策略*/  
  51.     @Override  
  52.     protected void configure(HttpSecurity http) throws Exception {  
  53.         http.authorizeRequests()//配置安全策略  
  54.             //.antMatchers("/","/hello").permitAll()//定义/请求不需要验证  
  55.             .anyRequest().authenticated()//其余的所有请求都需要验证  
  56.             .and()  
  57.         .logout()  
  58.             .permitAll()//定义logout不需要验证  
  59.             .and()  
  60.         .formLogin();//使用form表单登录  
  61.           
  62.         http.exceptionHandling().authenticationEntryPoint(casAuthenticationEntryPoint())  
  63.             .and()  
  64.             .addFilter(casAuthenticationFilter())  
  65.             .addFilterBefore(casLogoutFilter(), LogoutFilter.class)  
  66.             .addFilterBefore(singleSignOutFilter(), CasAuthenticationFilter.class);  
  67.           
  68.         //http.csrf().disable(); //禁用CSRF  
  69.     }  
  70.       
  71.     /**认证的入口*/  
  72.     @Bean  
  73.     public CasAuthenticationEntryPoint casAuthenticationEntryPoint() {  
  74.         CasAuthenticationEntryPoint casAuthenticationEntryPoint = new CasAuthenticationEntryPoint();  
  75.         casAuthenticationEntryPoint.setLoginUrl(casProperties.getCasServerLoginUrl());  
  76.         casAuthenticationEntryPoint.setServiceProperties(serviceProperties());  
  77.         return casAuthenticationEntryPoint;  
  78.     }  
  79.       
  80.     /**指定service相关信息*/  
  81.     @Bean  
  82.     public ServiceProperties serviceProperties() {  
  83.         ServiceProperties serviceProperties = new ServiceProperties();  
  84.         serviceProperties.setService(casProperties.getAppServerUrl() + casProperties.getAppLoginUrl());  
  85.         serviceProperties.setAuthenticateAllArtifacts(true);  
  86.         return serviceProperties;  
  87.     }  
  88.       
  89.     /**CAS认证过滤器*/  
  90.     @Bean  
  91.     public CasAuthenticationFilter casAuthenticationFilter() throws Exception {  
  92.         CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();  
  93.         casAuthenticationFilter.setAuthenticationManager(authenticationManager());  
  94.         casAuthenticationFilter.setFilterProcessesUrl(casProperties.getAppLoginUrl());  
  95.         return casAuthenticationFilter;  
  96.     }  
  97.       
  98.     /**cas 认证 Provider*/  
  99.     @Bean  
  100.     public CasAuthenticationProvider casAuthenticationProvider() {  
  101.         CasAuthenticationProvider casAuthenticationProvider = new CasAuthenticationProvider();  
  102.         casAuthenticationProvider.setAuthenticationUserDetailsService(customUserDetailsService());  
  103.         //casAuthenticationProvider.setUserDetailsService(customUserDetailsService()); //这里只是接口类型,实现的接口不一样,都可以的。  
  104.         casAuthenticationProvider.setServiceProperties(serviceProperties());  
  105.         casAuthenticationProvider.setTicketValidator(cas20ServiceTicketValidator());  
  106.         casAuthenticationProvider.setKey("casAuthenticationProviderKey");  
  107.         return casAuthenticationProvider;  
  108.     }  
  109.       
  110.     /*@Bean 
  111.     public UserDetailsService customUserDetailsService(){ 
  112.         return new CustomUserDetailsService(); 
  113.     }*/  
  114.       
  115.     /**用户自定义的AuthenticationUserDetailsService*/  
  116.     @Bean  
  117.     public AuthenticationUserDetailsService<CasAssertionAuthenticationToken> customUserDetailsService(){  
  118.         return new CustomUserDetailsService();  
  119.     }  
  120.       
  121.     @Bean  
  122.     public Cas20ServiceTicketValidator cas20ServiceTicketValidator() {  
  123.         return new Cas20ServiceTicketValidator(casProperties.getCasServerUrl());  
  124.     }  
  125.       
  126.     /**单点登出过滤器*/  
  127.     @Bean  
  128.     public SingleSignOutFilter singleSignOutFilter() {  
  129.         SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();  
  130.         singleSignOutFilter.setCasServerUrlPrefix(casProperties.getCasServerUrl());  
  131.         singleSignOutFilter.setIgnoreInitConfiguration(true);  
  132.         return singleSignOutFilter;  
  133.     }  
  134.       
  135.     /**请求单点退出过滤器*/  
  136.     @Bean  
  137.     public LogoutFilter casLogoutFilter() {  
  138.         LogoutFilter logoutFilter = new LogoutFilter(casProperties.getCasServerLogoutUrl(), new SecurityContextLogoutHandler());  
  139.         logoutFilter.setFilterProcessesUrl(casProperties.getAppLogoutUrl());  
  140.         return logoutFilter;  
  141.     }  
  142. }  

6.用户自定义类

      (1)定义CasProperties,用于将properties文件指定的内容注入以方便使用,这里不注入也是可以的,可以获取Spring 当前的环境,代码如下:
[java]  view plain  copy
  1. package com.chengli.springboot.properties;  
  2.   
  3. import org.springframework.beans.factory.annotation.Value;  
  4. import org.springframework.stereotype.Component;  
  5.   
  6. /** 
  7.  * CAS的配置参数 
  8.  * @author ChengLi 
  9.  */  
  10. @Component  
  11. public class CasProperties {  
  12.     @Value("${cas.server.host.url}")  
  13.     private String casServerUrl;  
  14.   
  15.     @Value("${cas.server.host.login_url}")  
  16.     private String casServerLoginUrl;  
  17.   
  18.     @Value("${cas.server.host.logout_url}")  
  19.     private String casServerLogoutUrl;  
  20.   
  21.     @Value("${app.server.host.url}")  
  22.     private String appServerUrl;  
  23.   
  24.     @Value("${app.login.url}")  
  25.     private String appLoginUrl;  
  26.   
  27.     @Value("${app.logout.url}")  
  28.     private String appLogoutUrl;  
  29. ......省略 getters setters 方法  
  30. }  

      (2)定义CustomUserDetailsService类,代码如下:
[java]  view plain  copy
  1. package com.chengli.springboot.custom;  
  2.   
  3. import java.util.HashSet;  
  4. import java.util.Set;  
  5.   
  6. import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;  
  7. import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;  
  8. import org.springframework.security.core.userdetails.UserDetails;  
  9. import org.springframework.security.core.userdetails.UsernameNotFoundException;  
  10.   
  11. /** 
  12.  * 用于加载用户信息 实现UserDetailsService接口,或者实现AuthenticationUserDetailsService接口 
  13.  * @author ChengLi 
  14.  * 
  15.  */  
  16. public class CustomUserDetailsService /* 
  17.     //实现UserDetailsService接口,实现loadUserByUsername方法 
  18.     implements UserDetailsService { 
  19.     @Override 
  20.     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 
  21.         System.out.println("当前的用户名是:"+username); 
  22.         //这里我为了方便,就直接返回一个用户信息,实际当中这里修改为查询数据库或者调用服务什么的来获取用户信息 
  23.         UserInfo userInfo = new UserInfo(); 
  24.         userInfo.setUsername("admin"); 
  25.         userInfo.setName("admin"); 
  26.         Set<AuthorityInfo> authorities = new HashSet<AuthorityInfo>(); 
  27.         AuthorityInfo authorityInfo = new AuthorityInfo("TEST"); 
  28.         authorities.add(authorityInfo); 
  29.         userInfo.setAuthorities(authorities); 
  30.         return userInfo; 
  31.     }*/  
  32.       
  33.       
  34.     //实现AuthenticationUserDetailsService,实现loadUserDetails方法  
  35.     implements AuthenticationUserDetailsService<CasAssertionAuthenticationToken> {  
  36.   
  37.     @Override  
  38.     public UserDetails loadUserDetails(CasAssertionAuthenticationToken token) throws UsernameNotFoundException {  
  39.         System.out.println("当前的用户名是:"+token.getName());  
  40.         /*这里我为了方便,就直接返回一个用户信息,实际当中这里修改为查询数据库或者调用服务什么的来获取用户信息*/  
  41.         UserInfo userInfo = new UserInfo();  
  42.         userInfo.setUsername("admin");  
  43.         userInfo.setName("admin");  
  44.         Set<AuthorityInfo> authorities = new HashSet<AuthorityInfo>();  
  45.         AuthorityInfo authorityInfo = new AuthorityInfo("TEST");  
  46.         authorities.add(authorityInfo);  
  47.         userInfo.setAuthorities(authorities);  
  48.         return userInfo;  
  49.     }  
  50.   
  51. }  

      (3)定义AuthorityInfo类,用于加载当前登录用户的权限信息,实现GrantedAuthority接口,代码如下:
[java]  view plain  copy
  1. package com.chengli.springboot.custom;  
  2.   
  3. import org.springframework.security.core.GrantedAuthority;  
  4.   
  5. /** 
  6.  * 权限信息 
  7.  *  
  8.  * @author ChengLi 
  9.  * 
  10.  */  
  11. public class AuthorityInfo implements GrantedAuthority {  
  12.     private static final long serialVersionUID = -175781100474818800L;  
  13.   
  14.     /** 
  15.      * 权限CODE 
  16.      */  
  17.     private String authority;  
  18.   
  19.     public AuthorityInfo(String authority) {  
  20.         this.authority = authority;  
  21.     }  
  22.   
  23.     @Override  
  24.     public String getAuthority() {  
  25.         return authority;  
  26.     }  
  27.   
  28.     public void setAuthority(String authority) {  
  29.         this.authority = authority;  
  30.     }  
  31.   
  32. }  

      (4)定义UserInfo类,用于加载当前用户信息,实现UserDetails接口,代码如下:
[java]  view plain  copy
  1. package com.chengli.springboot.custom;  
  2.   
  3. import java.util.Collection;  
  4. import java.util.HashSet;  
  5. import java.util.Set;  
  6.   
  7. import org.springframework.security.core.GrantedAuthority;  
  8. import org.springframework.security.core.userdetails.UserDetails;  
  9.   
  10. /** 
  11.  * 用户信息 
  12.  * @、这里我写了几个较为常用的字段,id,name,username,password,可以根据实际的情况自己增加 
  13.  * @author ChengLi 
  14.  * 
  15.  */  
  16. public class UserInfo implements UserDetails {  
  17.     private static final long serialVersionUID = -1041327031937199938L;  
  18.   
  19.     /** 
  20.      * 用户ID 
  21.      */  
  22.     private Long id;  
  23.   
  24.     /** 
  25.      * 用户名称 
  26.      */  
  27.     private String name;  
  28.   
  29.     /** 
  30.      * 登录名称 
  31.      */  
  32.     private String username;  
  33.   
  34.     /** 
  35.      * 登录密码 
  36.      */  
  37.     private String password;  
  38.   
  39.     private boolean isAccountNonExpired = true;  
  40.   
  41.     private boolean isAccountNonLocked = true;  
  42.   
  43.     private boolean isCredentialsNonExpired = true;  
  44.   
  45.     private boolean isEnabled = true;  
  46.   
  47.     private Set<AuthorityInfo> authorities = new HashSet<AuthorityInfo>();  
  48. ....省略getters setters 方法  
  49. }  

到这里基本就已经完成了,运行CAS Server ,将以上的application.properties文件中的地址修改为实际的地址即可运行。

参考:
https://github.com/xuanbo/spring-boot-cas-client

Viewing all articles
Browse latest Browse all 532

Trending Articles