spring security 跨域访问

本文分享了在前后端分离的场景下,如何解决SpringSecurity对跨域请求的拦截问题。作者通过在FILTER_SECURITY_INTERCEPTOR中判断请求类型,利用已有登录过滤器处理跨域请求,并更新用户权限,确保跨域后URL不再被拦截。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

哈哈,我又来了。这个springsecurity可折腾死我了,别的我觉着用不着记录,这个必须记录。去年搞了这个框架代替了自己写的权限机制,一是为了随大流,二是自己写的有线程问题。这下好了,遇到点新问题就不会解决,已解决就过了三天,弱爆了。

最近有一个旧系统,业务庞大,光数据表400多个,需要移植,一点点从原来的.net平台移植到java平台,这就涉及到两个平台的集成,自己写了个集成方案,旧系统访问新系统时就被springsecurity拦住了,按照网上的配置了放行无效果,人家都是springboot集成,代码配置,我时xml配置,也有人家自定义过滤器的,不过说的不明白,参杂了业务处理又缺代码,但是也给了我启示,特别有用的启示,一会把文章链接放上来。

先说我的解决方案:

1、就是请求传递一个标志,在标准的FILTER_SECURITY_INTERCEPTOR过滤器中分类处理,跨域的一波,正常的一波。正常的就不说了,我也是照抄的。跨域的也不用多写无用的代码,能用已经有的就用已经有的。例如:

//_requesType是跨域请求标志
        if(request.getParameter("_requesType")!=null&&session.getAttribute("SPRING_SECURITY_CONTEXT")==null) {
            //调用了已经定义好的登录过滤器,里面有证书、权限等各种处理
            AuthenticationFilter filter = (AuthenticationFilter) SpringContextUtil.getApplicationContext().getBean("loginFilter");
            //获取证书
            Authentication authentication= filter.attemptAuthentication(request, response);
            //放到上下文中,这一步很重要,不然第一次跨域可以访问,跨过去以后的url也还是被拦截
            SecurityContextHolder.getContext().setAuthentication(authentication);
            session.setAttribute("SPRING_SECURITY_CONTEXT",SecurityContextHolder.getContext());
            //调用了启动时就执行的整理角色、资源的类,这个类处理权限配对的,因为角色和资源有动态配对情况,为方便这个类里有更新证书的方法
            MySecurityMetadataSource securityMetadataSource = (MySecurityMetadataSource) SpringContextUtil.getBean("securityMetadataSource");
            securityMetadataSource.updateSource(session);
            //然后就通过了
            chain.doFilter(req, res);
            return;
        }

这一步参考:https://blog.youkuaiyun.com/lvhao2813/article/details/81974242

2、上一步中有个更新证书的方法,如下:

/**
     * 重载缓存,更新资源
     */
    public static void updateSource(HttpSession session){
        //重载缓存
        requestMap.clear();
        //调用工厂中已有的角色类,找所有角色
        IResourceService resourceService = (IResourceService) SpringContextUtil.getApplicationContext().getBean("resourceService");
        //找所有资源
        List<Resource> resourceList = resourceService.searchFlat(null,null).getRows();
        //配对
        for(Resource resource:resourceList)
        {
            AntPathRequestMatcher matcher = new AntPathRequestMatcher(resource.getAction());
            List<ConfigAttribute> roleList = new ArrayList<ConfigAttribute>();
            for(Object ob:resourceService.findRoleList(resource.getResourceId()))
            {
                SecurityConfig config = new SecurityConfig(((Role)ob).getName());
                roleList.add(config);
            }
            requestMap.put(matcher, roleList);
        }
        
        //更新当前用户角色
        SecurityContext context = (SecurityContext)session.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
        Authentication authentication = context.getAuthentication();
        OnlineUser user = (OnlineUser)authentication.getPrincipal();
        
        //修改后的新权限,authority里放的是rolename
        IRoleService roleService = (IRoleService) SpringContextUtil.getApplicationContext().getBean("roleService");
        List<String> roleNameList = roleService.findRoleNameByUserId(user.getUserID());
        String[] tempList = new String[roleNameList.size()];
        for(int i=0; i<roleNameList.size();i++){
            tempList[i]=roleNameList.get(i);
        }
        List<GrantedAuthority> authoritiesList = AuthorityUtils.createAuthorityList(tempList);
        user.setAuthorities(authoritiesList);
        //更新token,给证书
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user, authentication.getCredentials(),authoritiesList);
        authenticationToken.setDetails(authentication.getDetails());
        context.setAuthentication(authenticationToken);
        
        resourceList.clear();
        roleNameList.clear();
    }

这一步年代久远,参考的找不见了。

解决方法主要适用于前后端分离,一次请求的url大于一个的情况,如果是一个的话很简单。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值