springboot前后端分离接⼊cas技术⽅案及实现(⼆)1.在l中增加sso接⼊相关依赖
<!--cas-client-->
<dependency>
<groupId>org.jasig.cas.client</groupId>
<artifactId>cas-client-core</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-cas</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-aspectj</artifactId>
<version>${shiro.version}</version>
</dependency>
<!--单点登录-->
<dependency>
<groupId>org.pac4j</groupId>
<artifactId>pac4j-cas</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>io.buji</groupId>
<artifactId>buji-pac4j</artifactId>
<version>4.0.0</version>
<exclusions>
<exclusion>
<artifactId>shiro-web</artifactId>
<groupId>org.apache.shiro</groupId>
</exclusion>
</exclusions>
</dependency>
2. 在springboot项⽬的配置⽂件l新增以下配置项:
#cas配置
cas:
client-name: kb
server:
#cas服务端前缀,不是登录地
url: 127.0.0.1:8085/cas
project:
#当前客户端地址,即应⽤地址(域名)
url: 127.0.0.1:8088/kg
#前端⾸页地址,⽤于sso验证成功后重定向到此页⾯(注意不是登陆页⾯,是登陆成功后的⾸页)    ui-url: 127.0.0.1:11000/admin/#/home
3.重写ShiroConfig.java⽂件:
import io.buji.pac4j.filter.CallbackFilter;
import io.buji.pac4j.filter.LogoutFilter;
import io.buji.pac4j.filter.SecurityFilter;
import io.buji.pac4j.subject.Pac4jSubjectFactory;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.DefaultWebSecurityManager;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;
import onfig.Config;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import t.annotation.Bean;
import t.annotation.Configuration;
import t.annotation.DependsOn;
import Ordered;
import annotation.Order;
import org.springframework.web.filter.DelegatingFilterProxy;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* cas整合shiro
* @author jay
* @date 2019-12-20
*
springboot aop*/
@Configuration
public class CasShiroConfig {
/**
* 项⽬⼯程路径
*/
@Value("${cas.project.url}")
private String projectUrl;
/**
* 项⽬cas服务路径
* 项⽬cas服务路径
*/
@Value("${cas.server.url}")
private String casServerUrl;
/**
* 客户端名称
*/
@Value("${cas.client-name}")
private String clientName;
/**
* 单点登出的listener
*
* @return
*/
@SuppressWarnings({"rawtypes", "unchecked"})
@Bean
public ServletListenerRegistrationBean<?> singleSignOutHttpSessionListener() {
ServletListenerRegistrationBean bean = new ServletListenerRegistrationBean();
bean.setListener(new SingleSignOutHttpSessionListener());
bean.setEnabled(true);
return bean;
}
/**
* 单点登出filter
*
* @return
*/
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public FilterRegistrationBean singleSignOutFilter() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setName("singleSignOutFilter");
SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
singleSignOutFilter.setCasServerUrlPrefix(casServerUrl);
singleSignOutFilter.setIgnoreInitConfiguration(true);
bean.setFilter(singleSignOutFilter);
bean.addUrlPatterns("/*");
bean.setEnabled(true);
return bean;
}
@Bean("securityManager")
public DefaultWebSecurityManager securityManager(Pac4jSubjectFactory subjectFactory, CasRealm casRealm) {        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm(casRealm);
manager.setSubjectFactory(subjectFactory);
//        manager.setSessionManager(sessionManager); //去掉session管理
return manager;
}
@Bean
public CasRealm casRealm() {
CasRealm realm = new CasRealm();
// 使⽤⾃定义的realm
realm.setClientName(clientName);
realm.setCachingEnabled(false);
//暂时不使⽤缓存
realm.setAuthenticationCachingEnabled(false);
realm.setAuthorizationCachingEnabled(false);
realm.setAuthorizationCachingEnabled(false);
//realm.setAuthenticationCacheName("authenticationCache");
//realm.setAuthorizationCacheName("authorizationCache");
return realm;
}
/**
* 使⽤ pac4j 的 subjectFactory
*
* @return
*/
@Bean
public Pac4jSubjectFactory subjectFactory() {
return new Pac4jSubjectFactory();
}
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));
//  该值缺省为false,表⽰⽣命周期由SpringApplicationContext管理,设置为true则表⽰由ServletContainer管理        filterRegistration.addInitParameter("targetFilterLifecycle", "true");
filterRegistration.setEnabled(true);
filterRegistration.addUrlPatterns("/*");
filterRegistration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.FORWARD);
return filterRegistration;
}
/**
* 加载shiroFilter权限控制规则(从数据库读取然后配置)
*
* @param shiroFilterFactoryBean
*/
private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean) {
/*下⾯这些规则配置最好配置到配置⽂件中 */
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/kg/", "securityFilter");
filterChainDefinitionMap.put("/kg/ssoLogin", "securityFilter");
filterChainDefinitionMap.put("/kg/index", "securityFilter");
filterChainDefinitionMap.put("/kg/callback/**", "callbackFilter");
//filterChainDefinitionMap.put("kg/logout", "logout");
filterChainDefinitionMap.put("kg/ssoLogout", "ssoLogoutFilter");
//        filterChainDefinitionMap.put("/**","anon");
filterChainDefinitionMap.put("/**", "jwt");    //使⽤⾃⼰的过滤器
// filterChainDefinitionMap.put("/user/edit/**", "authc,perms[user:edit]");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
}
/**
* shiroFilter
*
* @param securityManager
* @param config
* @return
*/
@Bean("shiroFilter")
public ShiroFilterFactoryBean factory(DefaultWebSecurityManager securityManager, Config config) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
//shiroFilterFactoryBean.setUnauthorizedUrl("/403");
// 添加casFilter到shiroFilter中
loadShiroFilterChain(shiroFilterFactoryBean);
Map<String, Filter> filters = new HashMap<>(4);
//cas 资源认证
//cas 资源认证
SecurityFilter securityFilter = new SecurityFilter();
securityFilter.setConfig(config);
securityFilter.setClients(clientName);
filters.put("securityFilter", securityFilter);
//cas 认证后回调
CallbackFilter callbackFilter = new CallbackFilter();
callbackFilter.setConfig(config);
callbackFilter.setDefaultUrl(projectUrl);
filters.put("callbackFilter", callbackFilter);
//验证请求
filters.put("jwt", new JWTFilter());    //添加⾃⼰的过滤器
/
/ 注销
LogoutFilter logoutFilter = new LogoutFilter();
logoutFilter.setConfig(config);
logoutFilter.setCentralLogout(true);
logoutFilter.setLocalLogout(true);
logoutFilter.setDefaultUrl(projectUrl + "/callback?client_name=" + clientName);
filters.put("ssoLogoutFilter", logoutFilter);
shiroFilterFactoryBean.setFilters(filters);
return shiroFilterFactoryBean;
}
/**
* 下⾯的代码是添加注解⽀持
*/
@Bean
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
// 强制使⽤cglib,防⽌重复代理和可能引起代理出错的问题
// zhuanlan.zhihu/p/29161098
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
}
@Bean
public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
}
4.重写ShiroRealm.java⽂件
注意点:这⾥有个⼤坑,⼀定要注意重写supports⽅法增加对token类型的⽀持,不然会报类型不⽀持的错,导致后续所有权限验证失败,这个错折腾了最少三天才解决
import io.alm.Pac4jRealm;

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。