ajax/springboot访问地址异常及跨域问题
Access to XMLHttpRequest 博客申明
每个人的代码差异不同,不代表所有问题错误都出自于此,我只分享我出现问题的场景及原因
以下问题出现于 springboot整合shiro场景下
Access to XMLHttpRequest问题 提要:
异常如下
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); // 客户端缓存的时间,默认为1800(30分钟)
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);
}
编写不易,若对您有帮助,请点个赞再走吧!谢谢