我的 spring-boot 项目 (2.3.10.RELEASE ) 与 shiro (1.7.1) 将 pac4j-cas(3.9.0) 和 buji-pac4j(4.1.1) 更新到最新版本 (pac4j-cas :5.1.2 pac4j -cas:6.0.0),但是碰巧我不能在HTML中使用iframe(X-Frame-Options拒绝)并且ajax被禁止了,谁能告诉我我该如何处理这些问题
部分代码如下:
ShiroConfig
public class ShiroConfig {
private final ShiroCasParams shiroCasParams;
private final CacheManager cacheManager;
private final Config pac4jConfig;
/**
* 生命周期
* @return
*/
@Bean
public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
/**
* 单点登出的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.setLogoutCallbackPath(shiroCasParams.getCasServerUrlPrefix());
singleSignOutFilter.setIgnoreInitConfiguration(true);
bean.setFilter(singleSignOutFilter);
bean.addUrlPatterns("/*");
bean.setEnabled(true);
return bean;
}
/**
* 添加shiro的filter
*
* @return
*/
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));
filterRegistration.addInitParameter("targetFilterLifecycle", "true");
filterRegistration.setEnabled(true);
filterRegistration.addUrlPatterns("/*");
return filterRegistration;
}
/**
* 进一步配置shiroCasRealm
*
* @return ShiroCasRealm
*/
@Bean(name = "shiroCasRealm")
public ShiroCasRealm casRealm() {
ShiroCasRealm shiroCasRealm = new ShiroCasRealm();
shiroCasRealm.setName(shiroCasParams.getClientName());
shiroCasRealm.setCachingEnabled(false);
shiroCasRealm.setAuthorizationCachingEnabled(false);
shiroCasRealm.setAuthenticationCachingEnabled(false);
return shiroCasRealm;
}
/**
* 配置过滤策略
*
* @param securityManager
* @return
*/
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 设置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 设置登录地址
shiroFilterFactoryBean.setLoginUrl(shiroCasParams.getLoginUrl());
shiroFilterFactoryBean.setUnauthorizedUrl(shiroCasParams.getLoginUrl());
// 配置拦截地址
Map<String, Filter> filters = new HashMap<>(16);
// cas 资源认证拦截器
SecurityFilter securityFilter = new CsrfTokenFilter();
securityFilter.setConfig(pac4jConfig);
filters.put("securityFilter", securityFilter);
//cas 认证后回调拦截器
CallbackFilter callbackFilter = new CallbackFilter();
callbackFilter.setConfig(pac4jConfig);
callbackFilter.setDefaultUrl("/");
filters.put("callbackFilter", callbackFilter);
// 本地登出同步登出CAS服务器
LogoutFilter logoutFilter = new LogoutFilter();
logoutFilter.setConfig(pac4jConfig);
logoutFilter.setCentralLogout(true);
logoutFilter.setLocalLogout(true);
logoutFilter.setDefaultUrl(shiroCasParams.getLogoutUrl());
filters.put("logoutFilter", logoutFilter);
shiroFilterFactoryBean.setFilters(filters);
loadShiroFilterChain(shiroFilterFactoryBean);
return shiroFilterFactoryBean;
}
/**
* 1、当我们第一次访问客户端时,先去cas进行认证,成功后会返回一个ticket
* 2、返回的ticket地址在casRealm已经进行了配置,shiroServerUrlPrefix + casFilterUrlPattern
* 3、即地址为/shiro-cas,对该地址进行casFilter拦截
*/
private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean) {
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
for (String uri : SystemParams.getUN_LOGIN_URI()) {
filterChainDefinitionMap.put(uri, "anon");
}
//相当于/callback,见callbackFilter
filterChainDefinitionMap.put("/shiro-cas", "callbackFilter");
filterChainDefinitionMap.put("/logout", "logoutFilter");
filterChainDefinitionMap.put("/**", "securityFilter");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
}
/**
* 配置授权策略
*/
@Bean(name = "authenticator")
public ModularRealmAuthenticator modularRealmAuthenticator() {
ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
return authenticator;
}
/**
* 使用 pac4j 的 subjectFactory
* @return
*/
@Bean
public Pac4jSubjectFactory subjectFactory() {
return new Pac4jSubjectFactory();
}
/**
* 配置securityManager
*
* @param authenticator
* @return
*/
@Bean(name = "securityManager")
public DefaultWebSecurityManager securityManager(ModularRealmAuthenticator authenticator) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setAuthenticator(authenticator);
securityManager.setRealm(casRealm());
//新pac4jSubjectFactory,替换原来new casSubjectFactory()
securityManager.setSubjectFactory(subjectFactory());
securityManager.setCacheManager(getEhCacheManager(CacheConstant.SYS_AUTHORIZATION_CACHE));
return securityManager;
}
// 取消对session的配置,因为这会导致cas单点登出产生问题
/**
* Session配置
*
* @return
*/
@Bean
@ConditionalOnProperty(name = "spring.cache.type", havingValue = "jcache")
public WebSessionManager sessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setGlobalSessionTimeout(-1L);
sessionManager.setDeleteInvalidSessions(true);
sessionManager.setSessionIdUrlRewritingEnabled(false);
return sessionManager;
}
/**
* 开启shiro aop注解支持.
* 使用代理方式-所以需要开启代码支持
*
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
@Bean
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
advisorAutoProxyCreator.setProxyTargetClass(true);
return advisorAutoProxyCreator;
}
/**
* 权限缓存兼容Ehcache3
*
* @return
*/
private org.apache.shiro.cache.CacheManager getEhCacheManager(String name) {
Assert.notNull(cacheManager, "无Ehcache缓存支持!");
return new org.apache.shiro.cache.CacheManager() {
@Override
public <K, V> Cache<K, V> getCache(String s) throws CacheException {
return new ShiroEhcacheCache<K, V>(cacheManager.getCache(name));
}
};
}
public class CsrfTokenFilter extends SecurityFilter {
/**
* token验证
*/
private boolean tokenVerification(ServletRequest request, ServletResponse response) {
ShiroHttpServletRequest httpServletRequest = (ShiroHttpServletRequest) request;
//Get请求无需Token
//Get no need Token
if (StrUtil.equalsIgnoreCase(CommonConstant.HTTP_OPTIONS_GET, httpServletRequest.getMethod())) {
return Boolean.TRUE;
}
String token = httpServletRequest.getHeader(HttpConstant.TOKEN_HEADER);
if (StrUtil.isBlank(token)) {
return Boolean.FALSE;
} else {
return ShiroUserUtil.isLogin() && token.equals(ShiroUserUtil.getToken());
}
}
private boolean monitorVerification() {
if (StrUtil.isNotBlank(ShiroUserUtil.getMonitorId())) {
return CommonConstant.STATUS_YES.equals(ParamsUtil.Default.MONITOR.get());
}
return Boolean.TRUE;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
if (!ShiroUserUtil.isSaveUserProfile() && StrUtil.isBlank(servletRequest.getParameter("appId"))) {
((HttpServletResponse)servletResponse).sendRedirect("http://xxxxxx/");
return;
}
if (tokenVerification(servletRequest, servletResponse) && monitorVerification()) {
super.doFilter(servletRequest, servletResponse, filterChain);
}
}
}