Springboot+Security+Cas整合
java1234
共 11045字,需浏览 23分钟
·
2020-10-20 13:42
点击上方蓝色字体,选择“标星公众号”
优质文章,第一时间送达
一、pom.xml文件,加入以下内容
org.jasig.cas.client
cas-client-core
3.5.0
org.springframework.security
spring-security-cas
org.springframework.security
spring-security-taglibs
二、application.properties文件,加入以下内容
#CAS服务地址
security.cas.server.host.url=http://XXXXX/cas
#CAS服务登录地址
security.cas.server.host.login_url=${security.cas.server.host.url}/login
#CAS服务登出地址
security.cas.server.host.logout_url=${security.cas.server.host.url}/logout?service=${security.app.server.host.url}
#应用访问地址
security.app.server.host.url=http://localhost:8080
#应用登录地址
security.app.login.url=/user/login
#应用登出地址
security.app.logout.url=/logout
三、security配置文件SecurityConfig,项目启动的时候执行,初始化security和cas的设置
import org.XXX.service.CustomUserDetailsService;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
import org.jasig.cas.client.validation.Cas30ServiceTicketValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
import org.springframework.security.cas.authentication.CasAuthenticationProvider;
import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
import org.springframework.security.cas.web.CasAuthenticationFilter;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
/**
* Security的配置
*/
@Configuration
@EnableWebSecurity //启用web权限
@EnableGlobalMethodSecurity(prePostEnabled = true) //启用方法验证
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CasProperties casProperties;
/**定义认证用户信息获取来源,密码校验规则等*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
super.configure(auth);
auth.authenticationProvider(casAuthenticationProvider());
}
/**定义安全策略*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().and()
.headers()
.frameOptions().sameOrigin()
.xssProtection()
.block(true)
.and();
http
.headers()
.cacheControl()
.and()
.contentTypeOptions()
.and()
.httpStrictTransportSecurity()
.and()
.xssProtection();
http.authorizeRequests()//配置安全策略
.antMatchers("/","/home/**","/seach/**","/user/**").permitAll()//定义/请求不需要验证
.antMatchers("/login/**").authenticated()//login下请求需要验证
.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
http.csrf().ignoringAntMatchers("/api/**");
}
/**指定service相关信息*/
@Bean
public ServiceProperties serviceProperties() {
ServiceProperties serviceProperties = new ServiceProperties();
serviceProperties.setService(casProperties.getAppServerUrl() + casProperties.getAppLoginUrl());
serviceProperties.setAuthenticateAllArtifacts(true);
return serviceProperties;
}
/**认证的入口*/
@Bean
public CasAuthenticationEntryPoint casAuthenticationEntryPoint() {
CasAuthenticationEntryPoint casAuthenticationEntryPoint = new CasAuthenticationEntryPoint();
casAuthenticationEntryPoint.setLoginUrl(casProperties.getCasServerLoginUrl());
casAuthenticationEntryPoint.setServiceProperties(serviceProperties());
return casAuthenticationEntryPoint;
}
/**CAS认证过滤器*/
@Bean
public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();
casAuthenticationFilter.setAuthenticationManager(authenticationManager());
casAuthenticationFilter.setFilterProcessesUrl(casProperties.getAppLoginUrl());
return casAuthenticationFilter;
}
@Bean
public Cas30ServiceTicketValidator cas30ServiceTicketValidator() {
return new Cas30ServiceTicketValidator(casProperties.getCasServerUrl());
}
/**cas 认证 Provider*/
@Bean
public CasAuthenticationProvider casAuthenticationProvider() {
CasAuthenticationProvider casAuthenticationProvider = new CasAuthenticationProvider();
casAuthenticationProvider.setAuthenticationUserDetailsService(customUserDetailsService());
//casAuthenticationProvider.setUserDetailsService(customUserDetailsService()); //这里只是接口类型,实现的接口不一样,都可以的。
casAuthenticationProvider.setServiceProperties(serviceProperties());
casAuthenticationProvider.setTicketValidator(cas30ServiceTicketValidator());
casAuthenticationProvider.setKey("casAuthenticationProviderKey");
return casAuthenticationProvider;
}
/**用户自定义的AuthenticationUserDetailsService*/
@Bean
public AuthenticationUserDetailsServicecustomUserDetailsService(){
return new CustomUserDetailsService();
}
/**单点登出过滤器*/
@Bean
public SingleSignOutFilter singleSignOutFilter() {
SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
singleSignOutFilter.setCasServerUrlPrefix(casProperties.getCasServerUrl());
singleSignOutFilter.setIgnoreInitConfiguration(true);
return singleSignOutFilter;
}
/**请求单点退出过滤器*/
@Bean
public LogoutFilter casLogoutFilter() {
LogoutFilter logoutFilter = new LogoutFilter(casProperties.getCasServerLogoutUrl(), new SecurityContextLogoutHandler());
logoutFilter.setFilterProcessesUrl(casProperties.getAppLogoutUrl());
return logoutFilter;
}
}
四、CasProperties类,用于将properties文件指定的内容注入以方便使用
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* CAS的配置参数
*/
@Component
public class CasProperties {
@Value("${security.cas.server.host.url}")
private String casServerUrl;
@Value("${security.cas.server.host.login_url}")
private String casServerLoginUrl;
@Value("${security.cas.server.host.logout_url}")
private String casServerLogoutUrl;
@Value("${security.app.server.host.url}")
private String appServerUrl;
@Value("${security.app.login.url}")
private String appLoginUrl;
@Value("${security.app.logout.url}")
private String appLogoutUrl;
public String getCasServerUrl() {
return casServerUrl;
}
public void setCasServerUrl(String casServerUrl) {
this.casServerUrl = casServerUrl;
}
public String getCasServerLoginUrl() {
return casServerLoginUrl;
}
public void setCasServerLoginUrl(String casServerLoginUrl) {
this.casServerLoginUrl = casServerLoginUrl;
}
public String getCasServerLogoutUrl() {
return casServerLogoutUrl;
}
public void setCasServerLogoutUrl(String casServerLogoutUrl) {
this.casServerLogoutUrl = casServerLogoutUrl;
}
public String getAppServerUrl() {
return appServerUrl;
}
public void setAppServerUrl(String appServerUrl) {
this.appServerUrl = appServerUrl;
}
public String getAppLoginUrl() {
return appLoginUrl;
}
public void setAppLoginUrl(String appLoginUrl) {
this.appLoginUrl = appLoginUrl;
}
public String getAppLogoutUrl() {
return appLogoutUrl;
}
public void setAppLogoutUrl(String appLogoutUrl) {
this.appLogoutUrl = appLogoutUrl;
}
}
五、定义CustomUserDetailsService类
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.XXX.entity.AuthorityInfo;
import org.XXX.entity.UserInfo;
import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
/**
* 用于加载用户信息 实现UserDetailsService接口,或者实现AuthenticationUserDetailsService接口
*/
@Service
public class CustomUserDetailsService implements AuthenticationUserDetailsService{
@Override
public UserDetails loadUserDetails(CasAssertionAuthenticationToken token) throws UsernameNotFoundException {
// 结合具体的逻辑去实现用户认证,并返回继承UserDetails的用户对象;
System.out.println("当前的用户名是:"+token.getName());
//获取用户信息
UserInfo userInfo = new UserInfo();
userInfo.setUsername(token.getName());
userInfo.setRole("ROLE_USER");
MapuserAttributess = token.getAssertion().getPrincipal().getAttributes();
//System.out.println(userAttributess.toString());
if (userAttributess != null) {
userInfo.setId( String.valueOf(userAttributess.get("id")));
userInfo.setNickname( String.valueOf(userAttributess.get("nickname")));
userInfo.setRealName( String.valueOf(userAttributess.get("real_name")));
userInfo.setEmail( String.valueOf(userAttributess.get("email")));
userInfo.setCountryCode( String.valueOf(userAttributess.get("country_code")));
}
System.out.println(userInfo.toString());
return userInfo;
}
}
六、定义UserInfo类,用于加载当前用户信息,实现UserDetails接口
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
/**
* 用户信息
*/
public class UserInfo extends User implements UserDetails {
private static final long serialVersionUID = -1041327031937199938L;
private String id;
private String username;
private String email;
private String countryCode;
private String mobile;
private String nickname;
private String role;
private String realName;
private String password;
private boolean isAccountNonExpired = true; //是否过期
private boolean isAccountNonLocked = true;//账户未锁定为true
private boolean isCredentialsNonExpired = true;//证书不过期为true
private boolean isEnabled = true;//是否可用
@Override
public Collection extends GrantedAuthority> getAuthorities() {
if(this.getRole() == null || this.getRole().length() <1){
return AuthorityUtils.commaSeparatedStringToAuthorityList("");
}
else{
return AuthorityUtils.commaSeparatedStringToAuthorityList(this.getRole());
}
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getCountryCode() {
return countryCode;
}
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public String getRealName() {
return realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isAccountNonExpired() {
return isAccountNonExpired;
}
public void setAccountNonExpired(boolean isAccountNonExpired) {
this.isAccountNonExpired = isAccountNonExpired;
}
public boolean isAccountNonLocked() {
return isAccountNonLocked;
}
public void setAccountNonLocked(boolean isAccountNonLocked) {
this.isAccountNonLocked = isAccountNonLocked;
}
public boolean isCredentialsNonExpired() {
return isCredentialsNonExpired;
}
public void setCredentialsNonExpired(boolean isCredentialsNonExpired) {
this.isCredentialsNonExpired = isCredentialsNonExpired;
}
public boolean isEnabled() {
return isEnabled;
}
public void setEnabled(boolean isEnabled) {
this.isEnabled = isEnabled;
}
@Override
public String toString() {
return "UserInfo [id=" + id + ", username=" + username + ", email=" + email + ", countryCode=" + countryCode
+ ", mobile=" + mobile + ", nickname=" + nickname + ", role=" + role + ", realName=" + realName
+ ", password=" + password + ", isAccountNonExpired=" + isAccountNonExpired + ", isAccountNonLocked="
+ isAccountNonLocked + ", isCredentialsNonExpired=" + isCredentialsNonExpired + ", isEnabled="
+ isEnabled + "]";
}
}
七、启动服务端,登陆之后,回显数据
UserInfo [
id=XXXX,
username=XXXX,
email=XXXXX@163.com,
countryCode=null,
mobile=null,
nickname=null,
role=ROLE_USER,
realName=null,
password=null,
isAccountNonExpired=true,
isAccountNonLocked=true,
isCredentialsNonExpired=true,
isEnabled=true
]
八、常见错误(无限重定向 和 401错误)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:
https://blog.csdn.net/w_meng_h/article/details/86673630
粉丝福利:108本java从入门到大神精选电子书领取
???
?长按上方锋哥微信二维码 2 秒 备注「1234」即可获取资料以及 可以进入java1234官方微信群
感谢点赞支持下哈
评论