Shiro处理ajax跨域问题
A页面的ajax向后台请求发送后,Shiro会处理请求并重定向(authc,默认过滤器),此时后端向前端return数据时会发送到B页面上(即Shiro重定向页面)。A页面无法接收到返回数据则不会进行跳转(未响应)
ps:一个域名的js在未经允许不得读取另一个域名的内容。但不阻止你向另一个域名发送请求
解决方案
此时将FormAuthenticationFilter类中onAccessDenied方法重写并重新注入到authc中
import com.zy_shop.demo.util.JSONUtil;
import org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroFilterMapFactory extends PermissionsAuthorizationFilter {
private static final Logger logger = LoggerFactory.getLogger(ShiroFilterMapFactory.class);
/**
* shiro认证perms资源失败后回调方法
* @param servletRequest
* @param servletResponse
* @return
* @throws IOException
*/
@Override
protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException {
logger.info("----------权限控制-------------");
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
String header = httpServletRequest.getHeader("X-Requested-With");
boolean isAjax = "XMLHttpRequest" == header;
if (isAjax) {//如果是ajax返回指定格式数据
logger.info("----------AJAX请求拒绝-------------");
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("application/json");
//返回禁止访问json字符串
httpServletResponse.getWriter().write(JSONUtil.returnForbiddenResult());
} else {//如果是普通请求进行重定向
logger.info("----------普通请求拒绝-------------");
httpServletResponse.sendRedirect("/403");
}
return false;
}
package com.zy_shop.demo.shiro.config;
import com.zy_shop.demo.shiro.realm.CustomRealm;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.AnonymousFilter;
import org.apache.shiro.web.filter.authc.LogoutFilter;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.Filter;
@Configuration
public class ShiroConfig {
//不加这个注解不生效,具体不详
@Bean
@ConditionalOnMissingBean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
defaultAAP.setProxyTargetClass(true);
return defaultAAP;
}
//将自己的验证方式加入容器
@Bean
public CustomRealm myShiroRealm() {
CustomRealm customRealm = new CustomRealm();
return customRealm;
}
//权限管理,配置主要是Realm的管理认证
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
return securityManager;
}
//Filter工厂,设置对应的过滤条件和跳转条件
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//登录
shiroFilterFactoryBean.setLoginUrl("/logins");
//首页
shiroFilterFactoryBean.setSuccessUrl("/index");
//错误页面,认证不通过跳转
shiroFilterFactoryBean.setUnauthorizedUrl("/error");
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
shiroFilterFactoryBean.setUnauthorizedUrl("/404");
shiroFilterFactoryBean.setUnauthorizedUrl("/500");
Mapfilters = shiroFilterFactoryBean.getFilters();//获取filters
//将自定义的权限验证失败的过滤器ShiroFilterFactoryBean注入shiroFilter
filters.put("authc", new ShiroFilterMapFactory());
filters.put("anon", new AnonymousFilter());
filters.put("logout", new LogoutFilter());
MapfilterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/resources/**", "anon");
filterChainDefinitionMap.put("/loginSubmit", "anon");
filterChainDefinitionMap.put("/logout", "logout");
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
//加入注解的使用,不加入这个注解不生效
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}