Springboot+Security+Cas整合
點擊上方藍(lán)色字體,選擇“標(biāo)星公眾號”
優(yōu)質(zhì)文章,第一時間送達(dá)
一、pom.xml文件,加入以下內(nèi)容
????org.jasig.cas.client
????cas-client-core
????3.5.0
????org.springframework.security
????spring-security-cas
????org.springframework.security
????spring-security-taglibs
二、application.properties文件,加入以下內(nèi)容
#CAS服務(wù)地址?
security.cas.server.host.url=http://XXXXX/cas?
#CAS服務(wù)登錄地址?
security.cas.server.host.login_url=${security.cas.server.host.url}/login?
#CAS服務(wù)登出地址?
security.cas.server.host.logout_url=${security.cas.server.host.url}/logout?service=${security.app.server.host.url}
#應(yīng)用訪問地址?
security.app.server.host.url=http://localhost:8080
#應(yīng)用登錄地址
security.app.login.url=/user/login
#應(yīng)用登出地址?
security.app.logout.url=/logout?三、security配置文件SecurityConfig,項目啟動的時候執(zhí)行,初始化security和cas的設(shè)置
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權(quán)限
@EnableGlobalMethodSecurity(prePostEnabled?=?true)?//啟用方法驗證
public?class?SecurityConfig?extends?WebSecurityConfigurerAdapter?{
?@Autowired
?private?CasProperties?casProperties;
?
?/**定義認(rèn)證用戶信息獲取來源,密碼校驗規(guī)則等*/
?@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相關(guān)信息*/
?@Bean
?public?ServiceProperties?serviceProperties()?{
??ServiceProperties?serviceProperties?=?new?ServiceProperties();
??serviceProperties.setService(casProperties.getAppServerUrl()?+?casProperties.getAppLoginUrl());
??serviceProperties.setAuthenticateAllArtifacts(true);
??return?serviceProperties;
?}
?
?/**認(rèn)證的入口*/
?@Bean
?public?CasAuthenticationEntryPoint?casAuthenticationEntryPoint()?{
??CasAuthenticationEntryPoint?casAuthenticationEntryPoint?=?new?CasAuthenticationEntryPoint();
??casAuthenticationEntryPoint.setLoginUrl(casProperties.getCasServerLoginUrl());
??casAuthenticationEntryPoint.setServiceProperties(serviceProperties());
??return?casAuthenticationEntryPoint;
?}
?
?/**CAS認(rèn)證過濾器*/
?@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?認(rèn)證?Provider*/
?@Bean
?public?CasAuthenticationProvider?casAuthenticationProvider()?{
??CasAuthenticationProvider?casAuthenticationProvider?=?new?CasAuthenticationProvider();
??casAuthenticationProvider.setAuthenticationUserDetailsService(customUserDetailsService());
??//casAuthenticationProvider.setUserDetailsService(customUserDetailsService());?//這里只是接口類型,實現(xiàn)的接口不一樣,都可以的。
??casAuthenticationProvider.setServiceProperties(serviceProperties());
??casAuthenticationProvider.setTicketValidator(cas30ServiceTicketValidator());
??casAuthenticationProvider.setKey("casAuthenticationProviderKey");
??return?casAuthenticationProvider;
?}
?
?/**用戶自定義的AuthenticationUserDetailsService*/
?@Bean
?public?AuthenticationUserDetailsService?customUserDetailsService(){
??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文件指定的內(nèi)容注入以方便使用
import?org.springframework.beans.factory.annotation.Value;
import?org.springframework.stereotype.Component;
?
/**
?*?CAS的配置參數(shù)
?*/
@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;
?
/**
?*?用于加載用戶信息?實現(xiàn)UserDetailsService接口,或者實現(xiàn)AuthenticationUserDetailsService接口
?*/
@Service
public?class?CustomUserDetailsService?implements?AuthenticationUserDetailsService?{???????????
????@Override
????public?UserDetails?loadUserDetails(CasAssertionAuthenticationToken?token)?throws?UsernameNotFoundException?{
????????????????//?結(jié)合具體的邏輯去實現(xiàn)用戶認(rèn)證,并返回繼承UserDetails的用戶對象;
??System.out.println("當(dāng)前的用戶名是:"+token.getName());
??
??//獲取用戶信息
??UserInfo?userInfo?=?new?UserInfo();
??userInfo.setUsername(token.getName());
??userInfo.setRole("ROLE_USER");
??Map?userAttributess?=?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類,用于加載當(dāng)前用戶信息,實現(xiàn)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?+?"]";
?}
?
}
七、啟動服務(wù)端,登陸之后,回顯數(shù)據(jù)
UserInfo?[
?id=XXXX,?
?username=XXXX,?
[email protected],?
?countryCode=null,?
?mobile=null,?
?nickname=null,?
?role=ROLE_USER,?
?realName=null,?
?password=null,?
?isAccountNonExpired=true,?
?isAccountNonLocked=true,?
?isCredentialsNonExpired=true,?
?isEnabled=true
]
八、常見錯誤(無限重定向 和 401錯誤)
版權(quán)聲明:本文為博主原創(chuàng)文章,遵循?CC 4.0 BY-SA?版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接和本聲明。
本文鏈接:
https://blog.csdn.net/w_meng_h/article/details/86673630
粉絲福利:108本java從入門到大神精選電子書領(lǐng)取
???
?長按上方鋒哥微信二維碼?2 秒 備注「1234」即可獲取資料以及 可以進(jìn)入java1234官方微信群
感謝點贊支持下哈?
評論
圖片
表情
