mirror of https://github.com/dromara/MaxKey.git
spring-security-cas-demo
This commit is contained in:
parent
1550e996a5
commit
5eabd4892c
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.unicom.sso</groupId>
|
||||
<artifactId>sso-springboot-sample</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>sso-bigdata-cas-starter-demo</artifactId>
|
||||
<description>cas 单点登录demo</description>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!--单点登录依赖-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.unicom.sso</groupId>-->
|
||||
<!-- <artifactId>unicom-sso-bigdata-cas-springboot-starter</artifactId>-->
|
||||
<!-- <version>0.0.1-SNAPSHOT</version>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-cas</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,17 @@
|
|||
package com.unicom.sso.bigdata.cas.demo;
|
||||
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
/**
|
||||
* cas 单点
|
||||
* @author baihz10
|
||||
* @date 2023/7/7 15:18
|
||||
*/
|
||||
//@EnableCasClient
|
||||
@SpringBootApplication
|
||||
public class CasApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(CasApplication.class, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.unicom.sso.bigdata.cas.demo.config;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
public class AuthorityInfo implements GrantedAuthority {
|
||||
private static final long serialVersionUID = -175781100474818800L;
|
||||
|
||||
/**
|
||||
* 权限CODE
|
||||
*/
|
||||
private String authority;
|
||||
|
||||
public AuthorityInfo(String authority) {
|
||||
this.authority = authority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthority() {
|
||||
return authority;
|
||||
}
|
||||
|
||||
public void setAuthority(String authority) {
|
||||
this.authority = authority;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
package com.unicom.sso.bigdata.cas.demo.config;
|
||||
|
||||
import org.jasig.cas.client.session.SingleSignOutFilter;
|
||||
import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
|
||||
import org.jasig.cas.client.validation.Cas30ProxyTicketValidator;
|
||||
import org.jasig.cas.client.validation.Cas30ServiceTicketValidator;
|
||||
import org.jasig.cas.client.validation.TicketValidator;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.ProviderManager;
|
||||
import org.springframework.security.cas.ServiceProperties;
|
||||
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.core.Authentication;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
|
||||
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
||||
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
@Configuration
|
||||
public class CasConfig {
|
||||
|
||||
@Value("${cas.server.url}")
|
||||
private String casServerUrl;
|
||||
@Value("${base.url}")
|
||||
private String baseUrl;
|
||||
|
||||
@Bean
|
||||
public AuthenticationEntryPoint authenticationEntryPoint() {
|
||||
CasAuthenticationEntryPoint entryPoint = new CasAuthenticationEntryPoint();
|
||||
entryPoint.setLoginUrl(casServerUrl + "/login");
|
||||
entryPoint.setServiceProperties(this.serviceProperties());
|
||||
return entryPoint;
|
||||
}
|
||||
|
||||
@Bean
|
||||
protected AuthenticationManager authenticationManager() throws Exception {
|
||||
return new ProviderManager(this.casAuthenticationProvider());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
|
||||
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
||||
filter.setAuthenticationManager(this.authenticationManager());
|
||||
filter.setServiceProperties(this.serviceProperties());
|
||||
filter.setAuthenticationFailureHandler(this.authenticationFailureHandler());
|
||||
filter.setAuthenticationSuccessHandler(this.authenticationSuccessHandler());
|
||||
return filter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationSuccessHandler authenticationSuccessHandler() {
|
||||
AuthenticationSuccessHandler authenticationSuccessHandler = new SimpleUrlAuthenticationSuccessHandler();
|
||||
|
||||
return authenticationSuccessHandler;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationFailureHandler authenticationFailureHandler() {
|
||||
AuthenticationFailureHandler authenticationFailureHandler = new SimpleUrlAuthenticationFailureHandler();
|
||||
|
||||
return authenticationFailureHandler;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServiceProperties serviceProperties() {
|
||||
ServiceProperties serviceProperties = new ServiceProperties();
|
||||
serviceProperties.setService(baseUrl);
|
||||
serviceProperties.setSendRenew(false);
|
||||
return serviceProperties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TicketValidator ticketValidator() {
|
||||
return new Cas30ProxyTicketValidator(casServerUrl);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CasAuthenticationProvider casAuthenticationProvider() {
|
||||
CasAuthenticationProvider provider = new CasAuthenticationProvider();
|
||||
provider.setServiceProperties(this.serviceProperties());
|
||||
provider.setTicketValidator(this.ticketValidator());
|
||||
provider.setAuthenticationUserDetailsService(new UserDetailsServiceImpl());
|
||||
provider.setKey("CAS_PROVIDER_LOCALHOST");
|
||||
return provider;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityContextLogoutHandler securityContextLogoutHandler() {
|
||||
return new SecurityContextLogoutHandler();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LogoutFilter logoutFilter() {
|
||||
LogoutFilter logoutFilter = new LogoutFilter(casServerUrl + "/logout?service=" + baseUrl,
|
||||
securityContextLogoutHandler());
|
||||
logoutFilter.setFilterProcessesUrl("/logout/cas");
|
||||
return logoutFilter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SingleSignOutFilter singleSignOutFilter() {
|
||||
SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
|
||||
singleSignOutFilter.setIgnoreInitConfiguration(true);
|
||||
return singleSignOutFilter;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package com.unicom.sso.bigdata.cas.demo.config;
|
||||
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* CAS的配置参数
|
||||
*/
|
||||
@Component
|
||||
public class CasProperties {
|
||||
@Value("${cas.server.host.url}")
|
||||
private String casServerUrl;
|
||||
|
||||
@Value("${cas.server.host.login_url}")
|
||||
private String casServerLoginUrl;
|
||||
|
||||
@Value("${cas.server.host.logout_url}")
|
||||
private String casServerLogoutUrl;
|
||||
|
||||
@Value("${app.casEnable}")
|
||||
private boolean casEnable;
|
||||
|
||||
@Value("${app.server.host.url}")
|
||||
private String appServerUrl;
|
||||
|
||||
@Value("${app.login_url}")
|
||||
private String appLoginUrl;
|
||||
|
||||
@Value("${app.logout_url}")
|
||||
private String appLogoutUrl;
|
||||
|
||||
@Value("${app.web_url}")
|
||||
private String webUrl;
|
||||
|
||||
public String getWebUrl() {
|
||||
return webUrl;
|
||||
}
|
||||
|
||||
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 boolean isCasEnable() {
|
||||
return casEnable;
|
||||
}
|
||||
|
||||
public void setCasEnable(boolean casEnable) {
|
||||
this.casEnable = casEnable;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.unicom.sso.bigdata.cas.demo.config;
|
||||
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
|
||||
public class CustomUserDetailsService implements UserDetailsService {
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
|
||||
// 可自定义获取用户信息
|
||||
return new User("admin", "admin", true, true, true, true,
|
||||
AuthorityUtils.createAuthorityList("ROLE_ADMIN"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package com.unicom.sso.bigdata.cas.demo.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
|
||||
{
|
||||
@Autowired
|
||||
private TokenService tokenService;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||
throws ServletException, IOException
|
||||
{
|
||||
LoginUser loginUser = tokenService.getLoginUser(request);
|
||||
if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication()))
|
||||
{
|
||||
tokenService.verifyToken(loginUser);
|
||||
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
|
||||
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
|
||||
}
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,233 @@
|
|||
package com.unicom.sso.bigdata.cas.demo.config;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class LoginUser implements UserDetails
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 用户唯一标识
|
||||
*/
|
||||
private String token;
|
||||
|
||||
/**
|
||||
* 登录时间
|
||||
*/
|
||||
private Long loginTime;
|
||||
|
||||
/**
|
||||
* 过期时间
|
||||
*/
|
||||
private Long expireTime;
|
||||
|
||||
/**
|
||||
* 登录IP地址
|
||||
*/
|
||||
private String ipaddr;
|
||||
|
||||
/**
|
||||
* 登录地点
|
||||
*/
|
||||
private String loginLocation;
|
||||
|
||||
/**
|
||||
* 浏览器类型
|
||||
*/
|
||||
private String browser;
|
||||
|
||||
/**
|
||||
* 操作系统
|
||||
*/
|
||||
private String os;
|
||||
|
||||
/**
|
||||
* 权限列表
|
||||
*/
|
||||
private Set<String> permissions;
|
||||
|
||||
|
||||
public Long getUserId()
|
||||
{
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(Long userId)
|
||||
{
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public Long getDeptId()
|
||||
{
|
||||
return deptId;
|
||||
}
|
||||
|
||||
public void setDeptId(Long deptId)
|
||||
{
|
||||
this.deptId = deptId;
|
||||
}
|
||||
|
||||
public String getToken()
|
||||
{
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setToken(String token)
|
||||
{
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public LoginUser()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 账户是否未过期,过期无法验证
|
||||
*/
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public boolean isAccountNonExpired()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定用户是否解锁,锁定的用户无法进行身份验证
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public boolean isAccountNonLocked()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否可用 ,禁用的用户不能身份验证
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public boolean isEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public Long getLoginTime()
|
||||
{
|
||||
return loginTime;
|
||||
}
|
||||
|
||||
public void setLoginTime(Long loginTime)
|
||||
{
|
||||
this.loginTime = loginTime;
|
||||
}
|
||||
|
||||
public String getIpaddr()
|
||||
{
|
||||
return ipaddr;
|
||||
}
|
||||
|
||||
public void setIpaddr(String ipaddr)
|
||||
{
|
||||
this.ipaddr = ipaddr;
|
||||
}
|
||||
|
||||
public String getLoginLocation()
|
||||
{
|
||||
return loginLocation;
|
||||
}
|
||||
|
||||
public void setLoginLocation(String loginLocation)
|
||||
{
|
||||
this.loginLocation = loginLocation;
|
||||
}
|
||||
|
||||
public String getBrowser()
|
||||
{
|
||||
return browser;
|
||||
}
|
||||
|
||||
public void setBrowser(String browser)
|
||||
{
|
||||
this.browser = browser;
|
||||
}
|
||||
|
||||
public String getOs()
|
||||
{
|
||||
return os;
|
||||
}
|
||||
|
||||
public void setOs(String os)
|
||||
{
|
||||
this.os = os;
|
||||
}
|
||||
|
||||
public Long getExpireTime()
|
||||
{
|
||||
return expireTime;
|
||||
}
|
||||
|
||||
public void setExpireTime(Long expireTime)
|
||||
{
|
||||
this.expireTime = expireTime;
|
||||
}
|
||||
|
||||
public Set<String> getPermissions()
|
||||
{
|
||||
return permissions;
|
||||
}
|
||||
|
||||
public void setPermissions(Set<String> permissions)
|
||||
{
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities()
|
||||
{
|
||||
return new HashSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,251 @@
|
|||
package com.unicom.sso.bigdata.cas.demo.config;
|
||||
|
||||
import org.jasig.cas.client.session.SingleSignOutFilter;
|
||||
import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.cas.ServiceProperties;
|
||||
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.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
||||
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* spring security配置
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter
|
||||
{
|
||||
@Autowired
|
||||
private CasProperties casProperties;
|
||||
|
||||
@Autowired
|
||||
private CasUserDetailsService customUserDetailsService;
|
||||
|
||||
@Autowired
|
||||
private CasAuthenticationSuccessHandler casAuthenticationSuccessHandler;
|
||||
|
||||
/**
|
||||
* 自定义用户认证逻辑
|
||||
*/
|
||||
@Autowired
|
||||
private UserDetailsService userDetailsService;
|
||||
|
||||
/**
|
||||
* 认证失败处理类
|
||||
*/
|
||||
@Autowired
|
||||
private AuthenticationEntryPointImpl unauthorizedHandler;
|
||||
|
||||
/**
|
||||
* 退出处理类
|
||||
*/
|
||||
@Autowired
|
||||
private LogoutSuccessHandlerImpl logoutSuccessHandler;
|
||||
|
||||
/**
|
||||
* token认证过滤器
|
||||
*/
|
||||
@Autowired
|
||||
private JwtAuthenticationTokenFilter authenticationTokenFilter;
|
||||
|
||||
/**
|
||||
* 跨域过滤器
|
||||
*/
|
||||
@Autowired
|
||||
private CorsFilter corsFilter;
|
||||
|
||||
|
||||
/**
|
||||
* 解决 无法直接注入 AuthenticationManager
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Bean
|
||||
@Override
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
/**
|
||||
* anyRequest | 匹配所有请求路径
|
||||
* access | SpringEl表达式结果为true时可以访问
|
||||
* anonymous | 匿名可以访问
|
||||
* denyAll | 用户不能访问
|
||||
* fullyAuthenticated | 用户完全认证可以访问(非remember-me下自动登录)
|
||||
* hasAnyAuthority | 如果有参数,参数表示权限,则其中任何一个权限可以访问
|
||||
* hasAnyRole | 如果有参数,参数表示角色,则其中任何一个角色可以访问
|
||||
* hasAuthority | 如果有参数,参数表示权限,则其权限可以访问
|
||||
* hasIpAddress | 如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
|
||||
* hasRole | 如果有参数,参数表示角色,则其角色可以访问
|
||||
* permitAll | 用户可以任意访问
|
||||
* rememberMe | 允许通过remember-me登录的用户访问
|
||||
* authenticated | 用户登录后可访问
|
||||
*/
|
||||
@Override
|
||||
protected void configure(HttpSecurity httpSecurity) throws Exception {
|
||||
//开启cas
|
||||
if (casProperties.isCasEnable()) {
|
||||
httpSecurity
|
||||
// CSRF禁用,因为不使用session
|
||||
.csrf().disable()
|
||||
// 基于token,所以不需要session
|
||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
|
||||
// 过滤请求
|
||||
.authorizeRequests()
|
||||
// 对于登录login 验证码captchaImage 允许匿名访问
|
||||
//.antMatchers("/login", "/captchaImage").anonymous()
|
||||
.antMatchers(
|
||||
HttpMethod.GET,
|
||||
"/*.html",
|
||||
"/**/*.html",
|
||||
"/**/*.css",
|
||||
"/**/*.js"
|
||||
).permitAll()
|
||||
.antMatchers("/profile/**").anonymous()
|
||||
.antMatchers("/common/download**").anonymous()
|
||||
.antMatchers("/common/download/resource**").anonymous()
|
||||
.antMatchers("/swagger-ui.html").anonymous()
|
||||
.antMatchers("/swagger-resources/**").anonymous()
|
||||
.antMatchers("/webjars/**").anonymous()
|
||||
.antMatchers("/*/api-docs").anonymous()
|
||||
.antMatchers("/druid/**").anonymous()
|
||||
.antMatchers("/websocket/**").anonymous()
|
||||
.antMatchers("/magic/web/**").anonymous()
|
||||
// 除上面外的所有请求全部需要鉴权认证
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.headers().frameOptions().disable();
|
||||
//单点登录登出
|
||||
httpSecurity.logout().permitAll().logoutSuccessHandler(logoutSuccessHandler);
|
||||
// Custom JWT based security filter
|
||||
httpSecurity.addFilter(casAuthenticationFilter())
|
||||
.addFilterBefore(authenticationTokenFilter, CasAuthenticationFilter.class)
|
||||
//.addFilterBefore(casLogoutFilter(), LogoutFilter.class)
|
||||
.addFilterBefore(singleSignOutFilter(), CasAuthenticationFilter.class).exceptionHandling()
|
||||
//认证失败
|
||||
.authenticationEntryPoint(casAuthenticationEntryPoint());
|
||||
|
||||
// 添加CORS filter
|
||||
httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
|
||||
httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
|
||||
// disable page caching
|
||||
httpSecurity.headers().cacheControl();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 强散列哈希加密实现
|
||||
*/
|
||||
@Bean
|
||||
public BCryptPasswordEncoder bCryptPasswordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 身份认证接口
|
||||
*/
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// cas
|
||||
if (casProperties.isCasEnable()) {
|
||||
super.configure(auth);
|
||||
auth.authenticationProvider(casAuthenticationProvider());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 认证的入口
|
||||
*/
|
||||
@Bean
|
||||
public CasAuthenticationEntryPoint casAuthenticationEntryPoint() {
|
||||
CasAuthenticationEntryPoint casAuthenticationEntryPoint = new CasAuthenticationEntryPoint();
|
||||
casAuthenticationEntryPoint.setLoginUrl(casProperties.getCasServerLoginUrl());
|
||||
casAuthenticationEntryPoint.setServiceProperties(serviceProperties());
|
||||
return casAuthenticationEntryPoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定service相关信息
|
||||
*/
|
||||
@Bean
|
||||
public ServiceProperties serviceProperties() {
|
||||
ServiceProperties serviceProperties = new ServiceProperties();
|
||||
serviceProperties.setService(casProperties.getAppServerUrl() + casProperties.getAppLoginUrl());
|
||||
serviceProperties.setAuthenticateAllArtifacts(true);
|
||||
return serviceProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* CAS认证过滤器
|
||||
*/
|
||||
@Bean
|
||||
public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
|
||||
CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();
|
||||
casAuthenticationFilter.setAuthenticationManager(authenticationManager());
|
||||
casAuthenticationFilter.setFilterProcessesUrl(casProperties.getAppLoginUrl());
|
||||
casAuthenticationFilter.setAuthenticationSuccessHandler(casAuthenticationSuccessHandler);
|
||||
return casAuthenticationFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* cas 认证 Provider
|
||||
*/
|
||||
@Bean
|
||||
public CasAuthenticationProvider casAuthenticationProvider() {
|
||||
CasAuthenticationProvider casAuthenticationProvider = new CasAuthenticationProvider();
|
||||
casAuthenticationProvider.setAuthenticationUserDetailsService(customUserDetailsService);
|
||||
casAuthenticationProvider.setServiceProperties(serviceProperties());
|
||||
casAuthenticationProvider.setTicketValidator(cas20ServiceTicketValidator());
|
||||
casAuthenticationProvider.setKey("casAuthenticationProviderKey");
|
||||
return casAuthenticationProvider;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Cas20ServiceTicketValidator cas20ServiceTicketValidator() {
|
||||
return new Cas20ServiceTicketValidator(casProperties.getCasServerUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* 单点登出过滤器
|
||||
*/
|
||||
@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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package com.unicom.sso.bigdata.cas.demo.config;
|
||||
|
||||
public class TokenService {
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package com.unicom.sso.bigdata.cas.demo.config;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
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 java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
public class UserDetailsServiceImpl implements AuthenticationUserDetailsService<CasAssertionAuthenticationToken> {
|
||||
@Override
|
||||
public UserDetails loadUserDetails(CasAssertionAuthenticationToken token) throws UsernameNotFoundException {
|
||||
System.out.println("getCredentials:" + token.getCredentials());
|
||||
String username = token.getName();
|
||||
System.out.println(username);
|
||||
UserInfo userInfo = new UserInfo();
|
||||
userInfo.setUsername("admin");
|
||||
userInfo.setName("admin");
|
||||
Set<AuthorityInfo> authorities = new HashSet<AuthorityInfo>();
|
||||
AuthorityInfo authorityInfo = new AuthorityInfo("TEST");
|
||||
authorities.add(authorityInfo);
|
||||
userInfo.setAuthorities(authorities);
|
||||
return userInfo;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
package com.unicom.sso.bigdata.cas.demo.config;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class UserInfo implements UserDetails {
|
||||
private static final long serialVersionUID = -1041327031937199938L;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@Getter
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户名称
|
||||
*/
|
||||
@Getter
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 登录名称
|
||||
*/
|
||||
@Getter
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 登录密码
|
||||
*/
|
||||
@Getter
|
||||
private String password;
|
||||
|
||||
private boolean isAccountNonExpired = true;
|
||||
|
||||
private boolean isAccountNonLocked = true;
|
||||
|
||||
private boolean isCredentialsNonExpired = true;
|
||||
|
||||
private boolean isEnabled = true;
|
||||
|
||||
@Getter
|
||||
private Set<AuthorityInfo> authorities = new HashSet<AuthorityInfo>();
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public boolean isAccountNonExpired() {
|
||||
return isAccountNonExpired;
|
||||
}
|
||||
|
||||
public void setAccountNonExpired(boolean accountNonExpired) {
|
||||
isAccountNonExpired = accountNonExpired;
|
||||
}
|
||||
|
||||
public boolean isAccountNonLocked() {
|
||||
return isAccountNonLocked;
|
||||
}
|
||||
|
||||
public void setAccountNonLocked(boolean accountNonLocked) {
|
||||
isAccountNonLocked = accountNonLocked;
|
||||
}
|
||||
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return isCredentialsNonExpired;
|
||||
}
|
||||
|
||||
public void setCredentialsNonExpired(boolean credentialsNonExpired) {
|
||||
isCredentialsNonExpired = credentialsNonExpired;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return isEnabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
isEnabled = enabled;
|
||||
}
|
||||
|
||||
public void setAuthorities(Set<AuthorityInfo> authorities) {
|
||||
this.authorities = authorities;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package com.unicom.sso.bigdata.cas.demo.controller;
|
||||
|
||||
import org.jasig.cas.client.util.AbstractCasFilter;
|
||||
import org.jasig.cas.client.validation.Assertion;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* cas 回调地址
|
||||
* @author baihz10
|
||||
* @date 2023/7/7 15:44
|
||||
*/
|
||||
@Controller
|
||||
public class HelloController {
|
||||
|
||||
@GetMapping("/hello")
|
||||
public String home(Model model, HttpServletRequest request) {
|
||||
// String token =request.getParameter("token");
|
||||
// System.out.println("token : "+token);
|
||||
// Assertion assertion = (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
|
||||
//
|
||||
// String username= assertion.getPrincipal().getName();
|
||||
// System.out.println("cas user:"+username);
|
||||
//
|
||||
// username = Optional.ofNullable(username).orElse("anonymous");
|
||||
// Map<String, Object> attributes = Optional.ofNullable(assertion.getPrincipal().getAttributes()).orElse(new HashMap<>());
|
||||
//
|
||||
// model.addAttribute("username", username);
|
||||
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
System.out.println("当前用户信息:" + auth.getPrincipal());
|
||||
return "home";
|
||||
}
|
||||
|
||||
@GetMapping("/hello2")
|
||||
public String home2(Model model, HttpServletRequest request) {
|
||||
String token =request.getParameter("token");
|
||||
System.out.println("token : "+token);
|
||||
Assertion assertion = (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
|
||||
|
||||
String username= assertion.getPrincipal().getName();
|
||||
System.out.println("cas user:"+username);
|
||||
|
||||
username = Optional.ofNullable(username).orElse("anonymous");
|
||||
Map<String, Object> attributes = Optional.ofNullable(assertion.getPrincipal().getAttributes()).orElse(new HashMap<>());
|
||||
|
||||
model.addAttribute("username", username);
|
||||
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
System.out.println("当前用户信息:" + auth.getPrincipal());
|
||||
return "home";
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.unicom.sso.bigdata.cas.demo.controller;
|
||||
|
||||
import org.jasig.cas.client.util.AbstractCasFilter;
|
||||
import org.jasig.cas.client.validation.Assertion;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 控制类
|
||||
* @author baihz10
|
||||
* @date 2023/7/7 15:44
|
||||
*/
|
||||
@Controller
|
||||
public class SsoLoginController {
|
||||
|
||||
@GetMapping("/caslogin")
|
||||
public String home(Model model,HttpServletRequest request) {
|
||||
Assertion assertion = (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
|
||||
|
||||
String username= assertion.getPrincipal().getName();
|
||||
username = Optional.ofNullable(username).orElse("anonymous");
|
||||
model.addAttribute("username", username);
|
||||
return "cas/login";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
server.port=10002
|
||||
|
||||
#spring.profiles.active=cas-test
|
||||
|
||||
base.url=http://cas.demo.maxkey.top:10002
|
||||
cas.server.url=http://192.168.202.102:8080/sign/authz/cas
|
||||
|
||||
#CAS
|
||||
cas.server.host.url=http://192.168.202.102:8080/sign/authz/cas
|
||||
#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.casEnable=true
|
||||
app.server.host.url=http://192.168.202.102:${server.port}
|
||||
|
||||
#??????
|
||||
app.server.host.login_url=/
|
||||
#??????
|
||||
app.server.host.logout_url=/logout
|
||||
#??????
|
||||
app.server.host.web_url=http://192.168.202.102/index
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>sso cas demo</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2 >Login with CAS</h2>
|
||||
login user : [[${username}]]
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>home</title>
|
||||
</head>
|
||||
<body>
|
||||
hello cas
|
||||
<br>
|
||||
hello [[${username}]]
|
||||
userInfo: [[${userInfo}]]
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue