详解Spring Boot 使用Spring security 集成CAS
1.创建工程
创建Maven工程:springboot-security-cas
2.加入依赖
创建工程后,打开pom.xml,在pom.xml中加入以下内容:
org.springframework.boot spring-boot-starter-parent 1.4.3.RELEASE UTF-8 1.8 org.springframework.boot spring-boot-starter org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-security org.springframework.security spring-security-cas org.springframework.security spring-security-taglibs org.springframework.boot spring-boot-devtools true org.springframework.boot spring-boot-configuration-processor true org.springframework.boot spring-boot-maven-plugin
3.创建application.properties
创建application.properties文件,加入以下内容:
#CAS服务地址
cas.server.host.url=http://localhost:8081/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}
#应用访问地址
app.server.host.url=http://localhost:8080
#应用登录地址
app.login.url=/login
#应用登出地址
app.logout.url=/logout
4.创建入口启动类(MainConfig)
创建入口启动类MainConfig,完整代码如下:
packagecom.chengli.springboot;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importorg.springframework.security.access.prepost.PreAuthorize;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.RestController;
@RestController
@SpringBootApplication
publicclassMainConfig{
publicstaticvoidmain(String[]args){
SpringApplication.run(MainConfig.class,args);
}
@RequestMapping("/")
publicStringindex(){
return"访问了首页哦";
}
@RequestMapping("/hello")
publicStringhello(){
return"不验证哦";
}
@PreAuthorize("hasAuthority('TEST')")//有TEST权限的才能访问
@RequestMapping("/security")
publicStringsecurity(){
return"helloworldsecurity";
}
@PreAuthorize("hasAuthority('ADMIN')")//必须要有ADMIN权限的才能访问
@RequestMapping("/authorize")
publicStringauthorize(){
return"有权限访问";
}
/**这里注意的是,TEST与ADMIN只是权限编码,可以自己定义一套规则,根据实际情况即可*/
}
5.创建Security配置类(SecurityConfig)
创建Security配置类SecurityConfig,完整代码如下:
packagecom.chengli.springboot.security;
importorg.jasig.cas.client.session.SingleSignOutFilter;
importorg.jasig.cas.client.validation.Cas20ServiceTicketValidator;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.security.cas.ServiceProperties;
importorg.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
importorg.springframework.security.cas.authentication.CasAuthenticationProvider;
importorg.springframework.security.cas.web.CasAuthenticationEntryPoint;
importorg.springframework.security.cas.web.CasAuthenticationFilter;
importorg.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
importorg.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
importorg.springframework.security.config.annotation.web.builders.HttpSecurity;
importorg.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
importorg.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
importorg.springframework.security.core.userdetails.AuthenticationUserDetailsService;
importorg.springframework.security.web.authentication.logout.LogoutFilter;
importorg.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
importcom.chengli.springboot.custom.CustomUserDetailsService;
importcom.chengli.springboot.properties.CasProperties;
@Configuration
@EnableWebSecurity//启用web权限
@EnableGlobalMethodSecurity(prePostEnabled=true)//启用方法验证
publicclassSecurityConfigextendsWebSecurityConfigurerAdapter{
@Autowired
privateCasPropertiescasProperties;
/**定义认证用户信息获取来源,密码校验规则等*/
@Override
protectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{
super.configure(auth);
auth.authenticationProvider(casAuthenticationProvider());
//inMemoryAuthentication从内存中获取
//auth.inMemoryAuthentication().withUser("chengli").password("123456").roles("USER")
//.and().withUser("admin").password("123456").roles("ADMIN");
//jdbcAuthentication从数据库中获取,但是默认是以security提供的表结构
//usersByUsernameQuery指定查询用户SQL
//authoritiesByUsernameQuery指定查询权限SQL
//auth.jdbcAuthentication().dataSource(dataSource).usersByUsernameQuery(query).authoritiesByUsernameQuery(query);
//注入userDetailsService,需要实现userDetailsService接口
//auth.userDetailsService(userDetailsService);
}
/**定义安全策略*/
@Override
protectedvoidconfigure(HttpSecurityhttp)throwsException{
http.authorizeRequests()//配置安全策略
//.antMatchers("/","/hello").permitAll()//定义/请求不需要验证
.anyRequest().authenticated()//其余的所有请求都需要验证
.and()
.logout()
.permitAll()//定义logout不需要验证
.and()
.formLogin();//使用form表单登录
http.exceptionHandling().authenticationEntryPoint(casAuthenticationEntryPoint())
.and()
.addFilter(casAuthenticationFilter())
.addFilterBefore(casLogoutFilter(),LogoutFilter.class)
.addFilterBefore(singleSignOutFilter(),CasAuthenticationFilter.class);
//http.csrf().disable();//禁用CSRF
}
/**认证的入口*/
@Bean
publicCasAuthenticationEntryPointcasAuthenticationEntryPoint(){
CasAuthenticationEntryPointcasAuthenticationEntryPoint=newCasAuthenticationEntryPoint();
casAuthenticationEntryPoint.setLoginUrl(casProperties.getCasServerLoginUrl());
casAuthenticationEntryPoint.setServiceProperties(serviceProperties());
returncasAuthenticationEntryPoint;
}
/**指定service相关信息*/
@Bean
publicServicePropertiesserviceProperties(){
ServicePropertiesserviceProperties=newServiceProperties();
serviceProperties.setService(casProperties.getAppServerUrl()+casProperties.getAppLoginUrl());
serviceProperties.setAuthenticateAllArtifacts(true);
returnserviceProperties;
}
/**CAS认证过滤器*/
@Bean
publicCasAuthenticationFiltercasAuthenticationFilter()throwsException{
CasAuthenticationFiltercasAuthenticationFilter=newCasAuthenticationFilter();
casAuthenticationFilter.setAuthenticationManager(authenticationManager());
casAuthenticationFilter.setFilterProcessesUrl(casProperties.getAppLoginUrl());
returncasAuthenticationFilter;
}
/**cas认证Provider*/
@Bean
publicCasAuthenticationProvidercasAuthenticationProvider(){
CasAuthenticationProvidercasAuthenticationProvider=newCasAuthenticationProvider();
casAuthenticationProvider.setAuthenticationUserDetailsService(customUserDetailsService());
//casAuthenticationProvider.setUserDetailsService(customUserDetailsService());//这里只是接口类型,实现的接口不一样,都可以的。
casAuthenticationProvider.setServiceProperties(serviceProperties());
casAuthenticationProvider.setTicketValidator(cas20ServiceTicketValidator());
casAuthenticationProvider.setKey("casAuthenticationProviderKey");
returncasAuthenticationProvider;
}
/*@Bean
publicUserDetailsServicecustomUserDetailsService(){
returnnewCustomUserDetailsService();
}*/
/**用户自定义的AuthenticationUserDetailsService*/
@Bean
publicAuthenticationUserDetailsServicecustomUserDetailsService(){
returnnewCustomUserDetailsService();
}
@Bean
publicCas20ServiceTicketValidatorcas20ServiceTicketValidator(){
returnnewCas20ServiceTicketValidator(casProperties.getCasServerUrl());
}
/**单点登出过滤器*/
@Bean
publicSingleSignOutFiltersingleSignOutFilter(){
SingleSignOutFiltersingleSignOutFilter=newSingleSignOutFilter();
singleSignOutFilter.setCasServerUrlPrefix(casProperties.getCasServerUrl());
singleSignOutFilter.setIgnoreInitConfiguration(true);
returnsingleSignOutFilter;
}
/**请求单点退出过滤器*/
@Bean
publicLogoutFiltercasLogoutFilter(){
LogoutFilterlogoutFilter=newLogoutFilter(casProperties.getCasServerLogoutUrl(),newSecurityContextLogoutHandler());
logoutFilter.setFilterProcessesUrl(casProperties.getAppLogoutUrl());
returnlogoutFilter;
}
}
6.用户自定义类
(1)定义CasProperties,用于将properties文件指定的内容注入以方便使用,这里不注入也是可以的,可以获取Spring当前的环境,代码如下:
packagecom.chengli.springboot.properties;
importorg.springframework.beans.factory.annotation.Value;
importorg.springframework.stereotype.Component;
/**
*CAS的配置参数
*@authorChengLi
*/
@Component
publicclassCasProperties{
@Value("${cas.server.host.url}")
privateStringcasServerUrl;
@Value("${cas.server.host.login_url}")
privateStringcasServerLoginUrl;
@Value("${cas.server.host.logout_url}")
privateStringcasServerLogoutUrl;
@Value("${app.server.host.url}")
privateStringappServerUrl;
@Value("${app.login.url}")
privateStringappLoginUrl;
@Value("${app.logout.url}")
privateStringappLogoutUrl;
......省略getterssetters方法
}
(2)定义CustomUserDetailsService类,代码如下:
packagecom.chengli.springboot.custom;
importjava.util.HashSet;
importjava.util.Set;
importorg.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
importorg.springframework.security.core.userdetails.AuthenticationUserDetailsService;
importorg.springframework.security.core.userdetails.UserDetails;
importorg.springframework.security.core.userdetails.UsernameNotFoundException;
/**
*用于加载用户信息实现UserDetailsService接口,或者实现AuthenticationUserDetailsService接口
*@authorChengLi
*
*/
publicclassCustomUserDetailsService/*
//实现UserDetailsService接口,实现loadUserByUsername方法
implementsUserDetailsService{
@Override
publicUserDetailsloadUserByUsername(Stringusername)throwsUsernameNotFoundException{
System.out.println("当前的用户名是:"+username);
//这里我为了方便,就直接返回一个用户信息,实际当中这里修改为查询数据库或者调用服务什么的来获取用户信息
UserInfouserInfo=newUserInfo();
userInfo.setUsername("admin");
userInfo.setName("admin");
Setauthorities=newHashSet();
AuthorityInfoauthorityInfo=newAuthorityInfo("TEST");
authorities.add(authorityInfo);
userInfo.setAuthorities(authorities);
returnuserInfo;
}*/
//实现AuthenticationUserDetailsService,实现loadUserDetails方法
implementsAuthenticationUserDetailsService{
@Override
publicUserDetailsloadUserDetails(CasAssertionAuthenticationTokentoken)throwsUsernameNotFoundException{
System.out.println("当前的用户名是:"+token.getName());
/*这里我为了方便,就直接返回一个用户信息,实际当中这里修改为查询数据库或者调用服务什么的来获取用户信息*/
UserInfouserInfo=newUserInfo();
userInfo.setUsername("admin");
userInfo.setName("admin");
Setauthorities=newHashSet();
AuthorityInfoauthorityInfo=newAuthorityInfo("TEST");
authorities.add(authorityInfo);
userInfo.setAuthorities(authorities);
returnuserInfo;
}
}
(3)定义AuthorityInfo类,用于加载当前登录用户的权限信息,实现GrantedAuthority接口,代码如下:
packagecom.chengli.springboot.custom;
importorg.springframework.security.core.GrantedAuthority;
/**
*权限信息
*
*@authorChengLi
*
*/
publicclassAuthorityInfoimplementsGrantedAuthority{
privatestaticfinallongserialVersionUID=-175781100474818800L;
/**
*权限CODE
*/
privateStringauthority;
publicAuthorityInfo(Stringauthority){
this.authority=authority;
}
@Override
publicStringgetAuthority(){
returnauthority;
}
publicvoidsetAuthority(Stringauthority){
this.authority=authority;
}
}
(4)定义UserInfo类,用于加载当前用户信息,实现UserDetails接口,代码如下:
packagecom.chengli.springboot.custom;
importjava.util.Collection;
importjava.util.HashSet;
importjava.util.Set;
importorg.springframework.security.core.GrantedAuthority;
importorg.springframework.security.core.userdetails.UserDetails;
/**
*用户信息
*@、这里我写了几个较为常用的字段,id,name,username,password,可以根据实际的情况自己增加
*@authorChengLi
*
*/
publicclassUserInfoimplementsUserDetails{
privatestaticfinallongserialVersionUID=-1041327031937199938L;
/**
*用户ID
*/
privateLongid;
/**
*用户名称
*/
privateStringname;
/**
*登录名称
*/
privateStringusername;
/**
*登录密码
*/
privateStringpassword;
privatebooleanisAccountNonExpired=true;
privatebooleanisAccountNonLocked=true;
privatebooleanisCredentialsNonExpired=true;
privatebooleanisEnabled=true;
privateSetauthorities=newHashSet();
....省略getterssetters方法
}
到这里基本就已经完成了,运行CASServer,将以上的application.properties文件中的地址修改为实际的地址即可运行。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。