com.fhs.config.ShiroConfiguration Maven / Gradle / Ivy
The newest version!
package com.fhs.config;
import com.fhs.pagex.filter.PageXFilter;
import com.fhs.shiro.ShiroCasRealm;
import com.fhs.shiro.ShiroRealm;
import com.fhs.shiro.cache.ShiroSpringCacheManager;
import io.buji.pac4j.filter.CallbackFilter;
import io.buji.pac4j.filter.LogoutFilter;
import io.buji.pac4j.realm.Pac4jRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;
import org.pac4j.cas.client.CasClient;
import org.pac4j.cas.config.CasConfiguration;
import org.pac4j.cas.logout.DefaultCasLogoutHandler;
import org.pac4j.core.client.Clients;
import org.pac4j.core.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.JacksonJsonRedisSerializer;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* shiro 配置包含单点登录支持
*/
@Configuration
public class ShiroConfiguration{
/*
*cas server地址
*/
@Value("${shiro.cas.casServerUrlPrefix:}")
private String casServerUrlPrefix;
/*
* 当前工程对外提供的服务地址
*/
@Value("${shiro.cas.shiroServerUrlPrefix:}")
private String shiroServerUrlPrefix;
private String clientName = "sso";
@Value("${fhs.login.url:http://default.fhs-opensource.com}")
private String shrioLoginUrl;
@Value("${fhs.login.enable-cas}")
private boolean isEnableCas;
/*
* 权限认证失败跳转地址
*/
public static final String unauthorizedUrl = "/error/403.html";
@Bean
public Config config() {
// CAS
final CasConfiguration configuration = new CasConfiguration(casServerUrlPrefix + "/login", casServerUrlPrefix);
configuration.setAcceptAnyProxy(true);
CasClient casClient = new CasClient(configuration);
casClient.setCallbackUrl(shiroServerUrlPrefix + "/callback?client_name=" + clientName);
if(isEnableCas)
{
configuration.setLogoutHandler(shiroCasLogoutHandler());
}
casClient.setName(clientName);
final Clients clients = new Clients(shiroServerUrlPrefix + "/callback?client_name=" + clientName, casClient);
final Config config = new Config(clients);
return config;
}
/**
* 登出操作
* @return
*/
public DefaultCasLogoutHandler shiroCasLogoutHandler(){
DefaultCasLogoutHandler logoutHandler = new DefaultCasLogoutHandler();
return logoutHandler;
}
@Bean(name = "shiroRealm")
public AuthorizingRealm shiroRealm() {
if (isEnableCas) {
//使用MD5加密
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("MD5");
hashedCredentialsMatcher.setHashIterations(1024);
Pac4jRealm shiroRealms = new ShiroCasRealm();
//shiroRealms.setCredentialsMatcher(hashedCredentialsMatcher);
return shiroRealms;
}
return new ShiroRealm();
}
/**
* 自定义的缓存管理器
* @return 自定义缓存管理器
*/
@Bean(name = "shiroSpringCacheManager")
public ShiroSpringCacheManager shiroSpringCacheManager( RedisConnectionFactory factory) {
RedisTemplate template = new RedisTemplate();
template.setConnectionFactory(factory);
//定义key的序列化方式
JdkSerializationRedisSerializer valSerializer =new JdkSerializationRedisSerializer();
template.setValueSerializer(valSerializer);
GenericJackson2JsonRedisSerializer keySerializer = new GenericJackson2JsonRedisSerializer();
template.setKeySerializer(keySerializer);
template.afterPropertiesSet();
RedisCacheManager rcm = new RedisCacheManager(template);
//设置缓存过期时间
rcm.setDefaultExpiration(60);//秒
ShiroSpringCacheManager cacheManager = new ShiroSpringCacheManager();
cacheManager.setCacheManager(rcm);
return cacheManager;
}
@Bean(name = "securityManager")
@DependsOn({"shiroRealm","shiroSpringCacheManager"})
public DefaultWebSecurityManager securityManager(RedisConnectionFactory factory) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setCacheManager(shiroSpringCacheManager(factory));// 用户授权/认证信息Cache, 采用EhCache 缓存
/*if (isEnableCas) {
securityManager.setSubjectFactory(new CasSubjectFactory());
}*/
// SecurityUtils.setSecurityManager(securityManager);
securityManager.setRealm(shiroRealm());
return securityManager;
}
/**
* 使用工厂模式,创建并初始化ShiroFilter
*
* @param securityManager
* @return
*/
@DependsOn("shiroRealm")
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
String realLoginUrl = this.isEnableCas ? casServerUrlPrefix + "/login?service=" + shiroServerUrlPrefix + "/callback?client_name=" + clientName : shrioLoginUrl;
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl(realLoginUrl);
/*
* 登录成功后要跳转的连接,不设置的时候,会默认跳转到前一步的url
* 比如先在浏览器中输入了http://localhost:8080/userlist,但是现在用户却没有登录,于是会跳转到登录页面,等登录认证通过后,
* 页面会再次自动跳转到http://localhost:8080/userlist页面而不是登录成功后的index页面
* 建议不要设置这个字段
*/
// shiroFilterFactoryBean.setSuccessUrl(loginSuccessUrl);
// 设置无权限访问页面
shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
/*
* 添加casFilter到shiroFilter中,注意,casFilter需要放到shiroFilter的前面,
* 从而保证程序在进入shiro的login登录之前就会进入单点认证
*/
//自定义拦截器
Map filtersMap = new LinkedHashMap();
filtersMap.put("pagexFilter",new PageXFilter());
if(isEnableCas)
{
//设置pac4j回调Filter
CallbackFilter callbackFilter = new CallbackFilter();
callbackFilter.setConfig(config());
//callbackFilter.setDefaultUrl("/starter");
filtersMap.put("casFilter", callbackFilter);
// 注销 拦截器
LogoutFilter logoutFilter = new LogoutFilter();
logoutFilter.setConfig(config());
logoutFilter.setCentralLogout(true);
logoutFilter.setLocalLogout(true);
logoutFilter.setDefaultUrl(shiroServerUrlPrefix + "/callback?client_name=" + clientName);
filtersMap.put("logout",logoutFilter);
}
shiroFilterFactoryBean.setFilters(filtersMap);
loadShiroFilterChain(shiroFilterFactoryBean);
return shiroFilterFactoryBean;
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public FilterRegistrationBean singleSignOutFilter() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setName("singleSignOutFilter");
SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
singleSignOutFilter.setCasServerUrlPrefix(shiroServerUrlPrefix);
singleSignOutFilter.setIgnoreInitConfiguration(true);
bean.setFilter(singleSignOutFilter);
bean.addUrlPatterns("/*");
bean.setEnabled(true);
return bean;
}
/**
* 注册单点登出的listener
*
* @return
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public ServletListenerRegistrationBean> singleSignOutHttpSessionListener() {
ServletListenerRegistrationBean bean = new ServletListenerRegistrationBean();
bean.setListener(new SingleSignOutHttpSessionListener());
bean.setEnabled(true);
return bean;
}
/**
* 加载shiroFilter权限控制规则(从数据库读取然后配置),角色/权限信息由MyShiroCasRealm对象提供doGetAuthorizationInfo实现获取来的
* 生产中会将这部分规则放到数据库中
*
* @param shiroFilterFactoryBean
*/
private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean) {
/////////////////////// 下面这些规则配置最好配置到配置文件中,注意,此处加入的filter需要保证有序,所以用的LinkedHashMap ///////////////////////
Map filterChainDefinitionMap = new LinkedHashMap();
if(isEnableCas) {
filterChainDefinitionMap.put("/callback", "casFilter");
filterChainDefinitionMap.put("/logout", "logout");
}
filterChainDefinitionMap.put("/ms/pagex/*", "pagexFilter");
//2.不拦截的请求
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/images/**", "anon");
filterChainDefinitionMap.put("/page/**", "anon");
//4.登录过的不拦截
filterChainDefinitionMap.put("/ms/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy