0

我的 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);
        }
    }
}
4

0 回答 0