解决前后端分离shiro跨域问题

问题描述

在前后端分离整合shiro框架时,我发现shiro中的Subject主体只能在第一次访问时候拿到,甚至AuthenticationInfo认证完之后AuthorizationInfo授权不能通过

原因分析:

跨域时会先发送一个OPTIONS(预请求),这个预请求是不带AuthorizationInfo的,所以不能授权

解决方案:

在这里插入图片描述

public class CORSAuthenticationFilter extends FormAuthenticationFilter {

    private static final Logger logger = LoggerFactory.getLogger(CORSAuthenticationFilter.class);

    public CORSAuthenticationFilter() {
        super();
    }

    @Override
    public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        //Always return true if the request's method is OPTIONSif (request instanceof HttpServletRequest) {
        if (((HttpServletRequest) request).getMethod().toUpperCase().equals("OPTIONS")) {
            return true;
        }

return super.isAccessAllowed(request, response, mappedValue);
    }


    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletResponse res = (HttpServletResponse)response;
        res.setHeader("Access-Control-Allow-Origin", "*");
        res.setStatus(HttpServletResponse.SC_OK);
        res.setCharacterEncoding("UTF-8");
        PrintWriter writer = res.getWriter();
        Map<String, Object> map= new HashMap<>();
        map.put("code", 702);
        map.put("msg", "未登录");
//        writer.write(JSON.toJSONString(map));
        writer.close();
        return false;
    }
}

自定义Filter,此步一定不要漏了
在shiro的配置类中一定要自定义Filter,免得会使用默认的Filter

@Configuration
public class ShiroConfig {
    //1.创建shiroFilter  //负责拦截所有请求

    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //给filter设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);

        //自定义Filter
        Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();
        filters.put("corsAuthenticationFilter",corsAuthenticationFilter());
        shiroFilterFactoryBean.setFilters(filters);

        //配置系统受限资源
        //配置系统公共资源
        Map<String,String> map = new HashMap<String,String>();
        map.put("/login","anon");//anon 公共的资源路径,不需要认证,如果不设置登陆时候提交表单的url路径,则会死循环一直登录不上
        map.put("/logout","anon");
        map.put("/**","corsAuthenticationFilter");//corsAuthenticationFilter 请求这个资源需要认证和授权

        //默认认证界面路径---当认证不通过时跳转
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);

        return shiroFilterFactoryBean;
    }

    public CORSAuthenticationFilter corsAuthenticationFilter(){
        return new CORSAuthenticationFilter();
    }

    //2.创建安全管理器
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("getRealm") Realm realm){
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();

//        给安全管理器设置自定义MD5realm
        defaultWebSecurityManager.setRealm(realm);
        return defaultWebSecurityManager;
    }

    //3.创建自定义realm
    @Bean
    public Realm getRealm(RedisTemplate redisTemplate){
        CustomerRealm customerRealm = new CustomerRealm();

        //获取hash凭证匹配器
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();

        //设置加密算法为md5
        credentialsMatcher.setHashAlgorithmName("MD5");
//        设置散列次数
        credentialsMatcher.setHashIterations(1024);

//        修改凭证校验匹配器
        customerRealm.setCredentialsMatcher(credentialsMatcher);

        //开启缓存管理
        customerRealm.setCacheManager(new RedisCacheManager());
        //开启全局缓存
        customerRealm.setCachingEnabled(true);
        //开启认证缓存
        customerRealm.setAuthenticationCachingEnabled(true);
        customerRealm.setAuthenticationCacheName("authenticationCache");//设置缓存的字段名
        //开启授权缓存
        customerRealm.setAuthorizationCachingEnabled(true);
        customerRealm.setAuthorizationCacheName("authorizationCache");//设置缓存的字段名

        return customerRealm;
    }

}

此步千万别忘
在这里插入图片描述

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值