前言
因为前段时间工作需要,需要使用Shiro来集成单点登录系统,本篇文章记录一下集成中如何使用。
关于Shiro的基本使用,在这里也有一篇文章来介绍:超详细springboot+apache shiro+redis
有需要的朋友可以看看。
下面就直接附上代码,关键地方代码中都有注释。
@Configuration
public class ShiroCasConfiguration {
private Logger log = LoggerFactory.getLogger(ShiroCasConfiguration.class);
//Cas服务器地址
@Value("${sso_server}")
private String casServerUrlPrefix;
//触发本地进行Cas认证的地址
@Value("${self_server}")
private String casService;
//成功后需要返回的页面
@Value("${cas_successUrl}")
private String successUrl;
// 登录地址
public static String loginUrl;
@Bean(name = "casRealm")
public CasRealm myShiroCasRealm() {
// 如需要可以自定义认证Realm来继承CasRealm
// CustomCasRealm realm = new CustomCasRealm();
CasRealm realm = new CasRealm();
realm.setCachingEnabled(true);
realm.setAuthenticationCachingEnabled(true);
realm.setAuthenticationCacheName("authenticationCache");
realm.setAuthorizationCachingEnabled(true);
realm.setAuthorizationCacheName("authorizationCache");
//此出的IP地址一定是CAS 认证的地址。
realm.setCasServerUrlPrefix("http://xx.xx.xx/cas");
realm.setCasService(casService);
loginUrl = casServerUrlPrefix + "/login?service=" + casService;
log.info("loginUrl:[{}]", loginUrl);
return realm;
}
@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("/*");
return filterRegistration;
}
@Bean(name = "lifecycleBeanPostProcessor")
public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean
public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
daap.setProxyTargetClass(true);
return daap;
}
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(CasRealm casRealm) {
DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
dwsm.setRealm(casRealm);
// <!-- 用户授权/认证信息Cache, 采用EhCache 缓存 -->
// dwsm.setCacheManager(getEhCacheManager());
// 指定 SubjectFactory
dwsm.setSubjectFactory(new CasSubjectFactory());
return dwsm;
}
/**
* 不配置也行,看需要
*
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(
DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
aasa.setSecurityManager(securityManager);
return aasa;
}
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager,
CasFilter casFilter) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl(loginUrl);
// 登录成功后要跳转的连接
shiroFilterFactoryBean.setSuccessUrl(successUrl);
shiroFilterFactoryBean.setUnauthorizedUrl(loginUrl);
// 添加casFilter到shiroFilter中
Map<String, Filter> filters = new HashMap<String, Filter>();
//触发进行本地cas认证Filter的url
filters.put("casFilter", casFilter);
// authcFilter
FormAuthenticationFilter authcFilter = new FormAuthenticationFilter();
authcFilter.setLoginUrl(loginUrl);
authcFilter.setSuccessUrl(successUrl);
filters.put("authc", authcFilter);
// logoutFilter
LogoutFilter logoutFilter = new LogoutFilter();
logoutFilter.setRedirectUrl(loginUrl);
filters.put("logout", logoutFilter);
shiroFilterFactoryBean.setFilters(filters);
loadShiroFilterChain(shiroFilterFactoryBean);
return shiroFilterFactoryBean;
}
@Bean(name = "casFilter")
public CasFilter getCasFilter() {
CasFilter casFilter = new CasFilter();
casFilter.setName("casFilter");
casFilter.setEnabled(true);
// 登录失败后跳转的URL,也就是 Shiro 执行 CasRealm 的 doGetAuthenticationInfo
// 方法向CasServer验证tiket
casFilter.setFailureUrl(loginUrl);// 我们选择认证失败后再打开登录页面
return casFilter;
}
private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean) {
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
filterChainDefinitionMap.put("/cas", "casFilter");// shiro集成cas后,首先添加该规则
filterChainDefinitionMap.put("/**", "authc");// authc /anon /可以理解为不拦截
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
}
@Bean
public ServletListenerRegistrationBean singleSignOutHttpSessionListener() {
ServletListenerRegistrationBean bean = new ServletListenerRegistrationBean();
bean.setListener(new SingleSignOutHttpSessionListener());
// bean.setName(""); //默认为bean name
bean.setEnabled(true);
// bean.setOrder(Ordered.HIGHEST_PRECEDENCE); //设置优先级
return bean;
}
/**
* 注册单点登出filter
*
* @return
*/
@Bean
public FilterRegistrationBean singleSignOutFilter() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setName("singleSignOutFilter");
bean.setFilter(new SingleSignOutFilter());
bean.addUrlPatterns("/*");
bean.setEnabled(true);
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);// 防止其他filter冲突
return bean;
}
}