ajax/springboot跨域问题

1 篇文章 0 订阅

Access to XMLHttpRequest 博客申明

每个人的代码差异不同,不代表所有问题错误都出自于此,我只分享我出现问题的场景及原因

以下问题出现于 springboot整合shiro场景下

Access to XMLHttpRequest问题 提要:

异常如下 error01

HTML代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body background="img/loginMenu01.png">
helloWorld
<div>
    <form id="formLogin">
        用户名: <input type="text" name="username"><br/>
        密码: <input type="text" name="password"><br/>
        <input type="button" id="signIn" value="注册">
    </form>
</div>
</body>
<script type="text/javascript"  src="js/jquery-2.0.0.min.js"></script>
<script  >
    $(function() {
        var ApiUrl = "http://localhost:8080/demo/"

        $("#signIn").click(
            function () {
                $.ajax({
                    url: ApiUrl+"login/goSignIn",
                    type: "POST",
                    dataType: "json",
                    xhrFields: {withCredentials: true},
                    crossDomain: true,
                    data: $("#formLogin").serialize(),
                    success: function (data) {
                        console.log(data)
                        if (data.status != 200) {
                            alert(data.message);
                            return;
                        }
                        window.location.href = "index";
                    }
                });
            }
        )
    });
</script>
</html>

Contoller层代码

@CrossOrigin//跨域(CORS)支持
@RestController
@RequestMapping(value = "/login")
public class LoginController {
    @Autowired
    private LoginService loginService;

    @RequestMapping(value="/goSignIn",method = RequestMethod.POST)//注册
    public StateCodeUtil goSignIn(User user){
    StateCodeUtil stateCodeUtil=new StateCodeUtil();//返参工具类
    boolean isSame=loginService.querySameUser(user.getName);//验证是否已存在
    if(isSame){
        String saltPassword = SignInUtil.getSaltPassword(user.getName, user.getPassword);//密码加密
        System.out.println("注册账号:"+user.getName+"  盐值密码:"+saltPassword);
        loginService.saveUser(user.getName,saltPassword);//账号密码写入数据库
        stateCodeUtil.setCode(200);//returnCode
        stateCodeUtil.setMessage("注册成功");//returnMsg
        return stateCodeUtil;
        }
        stateCodeUtil.setCode(201);
        stateCodeUtil.setMessage("账号已被注册");
        return stateCodeUtil;
    }

WebConfig层代码

@Configuration//配置项目的CORS
public class MvcConfig  implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
      registry.addMapping("/**") // 添加请求映射,就是对哪些地址进行跨域处理
                        .allowedOrigins("*") // 特定来源的允许来源列表。这里配置*表示所以网站都可进行跨域,这里生产介意指定特定的地址
                        .allowedHeaders("*") // 允许请求头携带的标题: "Content-Type", "X-Requested-With", "accept", "Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers"
                        .allowCredentials(true) // 浏览器是否携带凭证
                        .allowedMethods("*") // 允许跨域的请求方式,可以进行指定:GET,POST
                        .maxAge(3600); // 客户端缓存的时间,默认为180030分钟)
        WebMvcConfigurer.super.addCorsMappings(registry);
    }
}

ShiroConfig层代码

@Configuration //该注解表示是一个配置类(等同于springmvc.xml)
public class ShiroConfig {
    @Bean //相当于springmvc中的bean标签,返回类型等同于是bean中的class属性,方法名等用于bean中标签的id属性
    public MyRealm myRealm(@Qualifier("credentialsMatcher") HashedCredentialsMatcher credentialsMatcher){
        MyRealm realm=new MyRealm();
        realm.setCredentialsMatcher(credentialsMatcher);//加载 配置加密   ,相当于<property name="credentialsMatcher" ref="credentialsMatcher">
        return  realm;
    }
    //配置加密
    @Bean
    public HashedCredentialsMatcher credentialsMatcher(){
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("MD5");//设置加密方式
        credentialsMatcher.setHashIterations(1024);//设置加密次数
        return credentialsMatcher;

    }

    //配置shiro安全管理器
    @Bean
    public DefaultWebSecurityManager webSecurityManager(@Qualifier("myRealm") MyRealm myRealm){
        DefaultWebSecurityManager webSecurityManager = new DefaultWebSecurityManager();
        webSecurityManager.setRealm(myRealm);//加载自定义的realm
//        webSecurityManager.setCacheManager();
//        webSecurityManager.setSessionManager();
        return webSecurityManager;
    }

    //配置shiro的过滤器
    @Bean
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("webSecurityManager") DefaultWebSecurityManager webSecurityManager){
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(webSecurityManager);
        Map<String,String> map =new HashMap<String,String>();
        map.put("/index","anon");
        map.put("/index","logout");
        map.put("/**","authc");
        shiroFilter.setFilterChainDefinitionMap(map);
        return shiroFilter;
    }



    /**
     * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),
     * 需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
     * 配置以下两个bean(DefaultAdvisorAutoProxyCreator(可选)
     * 和AuthorizationAttributeSourceAdvisor)即可实现此功能
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

    /**
     * 设置授权注解@RequirePermission ,@hasRole的使用
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        System.out.println("执行AuthorizationAttributeSourceAdvisor==" + securityManager);
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
}

application.properties

server.port=8080
server.servlet.context-path=/demo

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql:///emp?serverTimezone=GMT%2B8
spring.datasource.username=root2001
spring.datasource.password=root2001

Access to XMLHttpRequest 异常原因一:

错误原因:
在配置ShiroConfig层代码时,方法ShiroFilterFactoryBean (Shiro过滤) 中

访问规则配置将authc 的参数设置为了 /** 所以访问接口时进行了拦截验证。

Value解释
anon无需认证可以访问
authc必须认证才能访问
user如果使用rememberMe的功能可以直接访问
authc该资源必须得到权限才可以访问
role该资源必须得到角色权限才可以访问

刚好这个接口时注册功能,所以必然没有访问的权限,所以导致了截图所出现的错误。

解决办法

改前

  //配置shiro的过滤器
    @Bean
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("webSecurityManager") DefaultWebSecurityManager webSecurityManager){
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(webSecurityManager);
        Map<String,String> map =new HashMap<String,String>();

        map.put("/index","anon");
        map.put("/index","logout");
       	map.put("/**","authc");	//修改此处
        shiroFilter.setFilterChainDefinitionMap(map);
        return shiroFilter;
    }

改后

  //配置shiro的过滤器
    @Bean
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("webSecurityManager") DefaultWebSecurityManager webSecurityManager){
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(webSecurityManager);
        Map<String,String> map =new HashMap<String,String>();

        map.put("/index","anon");
        map.put("/index","logout");
        map.put("/login/goLogin","authc"); //修改此处(不填写注册功能的接口即可)
        shiroFilter.setFilterChainDefinitionMap(map);
        return shiroFilter;
    }

Access to XMLHttpRequest 异常原因二:

SpringBoot升级 2.4.0 时所出现的问题:When allowCredentials is true, allowedOrigins cannot contain the specia

解决办法1

将springboot版本换到2.4.0以下

改前

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

改后

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

解决办法2

将.WebConfig层的代码 allowedOrigins替换成.allowedOriginPatterns即可。

改前

@Configuration//配置项目的CORS
public class MvcConfig  implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
           registry.addMapping("/**")
                .allowedOrigins("*") //修改此处
                .allowedHeaders("*") 
                .allowCredentials(true) 
                .allowedMethods("*") 
                .maxAge(3600); 
        WebMvcConfigurer.super.addCorsMappings(registry);
    }

改后

@Configuration//配置项目的CORS
public class MvcConfig  implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
           registry.addMapping("/**") 
               .allowedOriginPatterns("*") //修改此处
                .allowedHeaders("*") 
                .allowCredentials(true) 
                .allowedMethods("*")
                .maxAge(3600); 
        WebMvcConfigurer.super.addCorsMappings(registry);
    }

编写不易,若对您有帮助,请点个赞再走吧!谢谢

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值