欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SpringBoot使用CROS解决跨域问题

程序员文章站 2022-07-10 08:07:11
...

跨域问题其实之前就有说过,不明白的可以参考我之前的文章,这章主要讲解SpringBoot CROS的支持。

这里主要按照官方文档方式讲述。

SpringBoot CROS 参考: http://docs.spring.io/spring-boot/docs/1.5.4.RELEASE/reference/htmlsingle/#boot-features-cors

Spring CROS 参考: http://docs.spring.io/spring/docs/4.3.9.RELEASE/spring-framework-reference/htmlsingle/#cors

一、代码准备

SpringBoot使用CROS解决跨域问题

首先是支持Restful的controller,这里就不使用数据库了,简单一点。 UserController.class

  1. package cn.saytime.web;
  2. import cn.saytime.bean.JsonResult;
  3. import cn.saytime.bean.User;
  4. import org.springframework.http.ResponseEntity;
  5. import org.springframework.web.bind.annotation.CrossOrigin;
  6. import org.springframework.web.bind.annotation.PathVariable;
  7. import org.springframework.web.bind.annotation.RequestBody;
  8. import org.springframework.web.bind.annotation.RequestMapping;
  9. import org.springframework.web.bind.annotation.RequestMethod;
  10. import org.springframework.web.bind.annotation.RestController;
  11. import java.util.ArrayList;
  12. import java.util.Collections;
  13. import java.util.Date;
  14. import java.util.HashMap;
  15. import java.util.List;
  16. import java.util.Map;
  17. /**
  18. * @author zh
  19. * @ClassName cn.saytime.web.UserController
  20. * @Description
  21. */
  22. @RestController
  23. public class UserController {
  24. // 创建线程安全的Map
  25. static Map<Integer, User> users = Collections.synchronizedMap(new HashMap<Integer, User>());
  26. /**
  27. * 根据ID查询用户
  28. * @param id
  29. * @return
  30. */
  31. @RequestMapping(value = "user/{id}", method = RequestMethod.GET)
  32. public ResponseEntity<JsonResult> getUserById (@PathVariable(value = "id") Integer id){
  33. JsonResult r = new JsonResult();
  34. try {
  35. User user = users.get(id);
  36. r.setResult(user);
  37. r.setStatus("ok");
  38. } catch (Exception e) {
  39. r.setResult(e.getClass().getName() + ":" + e.getMessage());
  40. r.setStatus("error");
  41. e.printStackTrace();
  42. }
  43. return ResponseEntity.ok(r);
  44. }
  45. /**
  46. * 查询用户列表
  47. * @return
  48. */
  49. @CrossOrigin
  50. @RequestMapping(value = "users", method = RequestMethod.GET)
  51. public ResponseEntity<JsonResult> getUserList (){
  52. JsonResult r = new JsonResult();
  53. try {
  54. List<User> userList = new ArrayList<User>(users.values());
  55. r.setResult(userList);
  56. r.setStatus("ok");
  57. } catch (Exception e) {
  58. r.setResult(e.getClass().getName() + ":" + e.getMessage());
  59. r.setStatus("error");
  60. e.printStackTrace();
  61. }
  62. return ResponseEntity.ok(r);
  63. }
  64. /**
  65. * 添加用户
  66. * @param user
  67. * @return
  68. */
  69. @RequestMapping(value = "user", method = RequestMethod.POST)
  70. public ResponseEntity<JsonResult> add (@RequestBody User user){
  71. JsonResult r = new JsonResult();
  72. try {
  73. users.put(user.getId(), user);
  74. r.setResult(user.getId());
  75. r.setStatus("ok");
  76. } catch (Exception e) {
  77. r.setResult(e.getClass().getName() + ":" + e.getMessage());
  78. r.setStatus("error");
  79. e.printStackTrace();
  80. }
  81. return ResponseEntity.ok(r);
  82. }
  83. /**
  84. * 根据id删除用户
  85. * @param id
  86. * @return
  87. */
  88. @RequestMapping(value = "user/{id}", method = RequestMethod.DELETE)
  89. public ResponseEntity<JsonResult> delete (@PathVariable(value = "id") Integer id){
  90. JsonResult r = new JsonResult();
  91. try {
  92. users.remove(id);
  93. r.setResult(id);
  94. r.setStatus("ok");
  95. } catch (Exception e) {
  96. r.setResult(e.getClass().getName() + ":" + e.getMessage());
  97. r.setStatus("error");
  98. e.printStackTrace();
  99. }
  100. return ResponseEntity.ok(r);
  101. }
  102. /**
  103. * 根据id修改用户信息
  104. * @param user
  105. * @return
  106. */
  107. @RequestMapping(value = "user/{id}", method = RequestMethod.PUT)
  108. public ResponseEntity<JsonResult> update (@PathVariable("id") Integer id, @RequestBody User user){
  109. JsonResult r = new JsonResult();
  110. try {
  111. User u = users.get(id);
  112. u.setUsername(user.getUsername());
  113. u.setAge(user.getAge());
  114. users.put(id, u);
  115. r.setResult(u);
  116. r.setStatus("ok");
  117. } catch (Exception e) {
  118. r.setResult(e.getClass().getName() + ":" + e.getMessage());
  119. r.setStatus("error");
  120. e.printStackTrace();
  121. }
  122. return ResponseEntity.ok(r);
  123. }
  124. }

User.class

  1. package cn.saytime.bean;
  2. import java.util.Date;
  3. /**
  4. * @author zh
  5. * @ClassName cn.saytime.bean.User
  6. * @Description
  7. */
  8. public class User {
  9. private int id;
  10. private String username;
  11. private int age;
  12. private Date ctm;
  13. // Getter Setter
  14. }

JsonResult.class

  1. package cn.saytime.bean;
  2. public class JsonResult {
  3. private String status = null;
  4. private Object result = null;
  5. // Getter Setter
  6. }

二、测试是否存在跨域问题

我们在static目录新建一个test.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.bootcss.com/jquery/2.1.0/jquery.min.js"></script>
  7. <script type="text/javascript">
  8. function crosRequest(){
  9. $.ajax({
  10. url:'http://localhost:8080/users',
  11. type:'get',
  12. dataType:'json',
  13. success:function(data){
  14. console.log(data);
  15. }
  16. });
  17. }
  18. </script>
  19. </head>
  20. <body>
  21. <button onclick="crosRequest()">请求跨域资源</button>
  22. </body>
  23. </html>
  1. 我们使用IDEA的浏览器预览功能,点击谷歌小图标,可以看到打开网址为: http://localhost:63342/springboot-demo/springboot-cros/static/test.html?_ijt=ibtt432ffb9rh0vffqkkug3je8
  2. 启动SpringBoot工程,默认8080

不是使用IDEA的用户,自己找个tomcat启动test.html页面,修改端口为其他,然后启动springboot。

SpringBoot使用CROS解决跨域问题

SpringBoot使用CROS解决跨域问题

所以证明存在跨域问题。

一、@CrossOrigin注解方式 Controller method CORS configuration

这里我们在users映射的方法getUserList上面加上@CrossOrigin

  1. @CrossOrigin
  2. @RequestMapping(value = "users", method = RequestMethod.GET)
  3. public ResponseEntity<JsonResult> getUserList ()

然后再次使用上面的方式访问。

SpringBoot使用CROS解决跨域问题

表示跨域问题解决。 default @CrossOrigin allows all origins and the HTTP methods specified in the @RequestMapping annotation 上面的官方文档说明,也就是默认的@CrossOrigin允许所有跨域请求。

通过查看CrossOrigin源码可以看到, 默认配置为:

  1. "Access-Control-Allow-Origin" : "*"
  2. "Access-Control-Allow-Methods" : "GET,POST,PUT,OPTIONS"
  3. "Access-Control-Allow-Credentials" : "true"
  1. @Target({ElementType.METHOD, ElementType.TYPE})
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. public @interface CrossOrigin {
  5. /** @deprecated */
  6. @Deprecated
  7. String[] DEFAULT_ORIGINS = new String[]{"*"};
  8. /** @deprecated */
  9. @Deprecated
  10. String[] DEFAULT_ALLOWED_HEADERS = new String[]{"*"};
  11. /** @deprecated */
  12. @Deprecated
  13. boolean DEFAULT_ALLOW_CREDENTIALS = true;
  14. /** @deprecated */
  15. @Deprecated
  16. long DEFAULT_MAX_AGE = 1800L;
  17. @AliasFor("origins")
  18. String[] value() default {};
  19. @AliasFor("value")
  20. String[] origins() default {};
  21. String[] allowedHeaders() default {};
  22. String[] exposedHeaders() default {};
  23. RequestMethod[] methods() default {};
  24. String allowCredentials() default "";
  25. long maxAge() default -1L;
  26. }

It is also possible to enable CORS for the whole controller 也可以用在整个Controller类上面。即该controller所有映射都支持跨域请求。

  1. @CrossOrigin(origins = "http://domain2.com",
  2. maxAge = 3600,
  3. methods = {RequestMethod.GET, RequestMethod.POST})
  4. @RestController
  5. public class UserController

二、全局CORS配置

Global CORS configuration In addition to fine-grained, annotation-based configuration you’ll probably want to define some global CORS configuration as well. This is similar to using filters but can be declared withing Spring MVC and combined with fine-grained @CrossOrigin configuration. By default all origins and GET, HEAD and POST methods are allowed.

  1. package cn.saytime.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.web.servlet.config.annotation.CorsRegistry;
  5. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  6. import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
  7. /**
  8. * @author zh
  9. * @ClassName cn.saytime.config.CORSConfiguration
  10. * @Description
  11. */
  12. @Configuration
  13. public class CORSConfiguration {
  14. @Bean
  15. public WebMvcConfigurer corsConfigurer() {
  16. return new WebMvcConfigurerAdapter() {
  17. @Override
  18. public void addCorsMappings(CorsRegistry registry) {
  19. // registry.addMapping("/api/**");
  20. registry.addMapping("/**")
  21. .allowedOrigins("http://domain.com", "http://domain2.com")
  22. .allowedMethods("GET", "POST", "DELETE", "PUT", "OPTIONS")
  23. .allowCredentials(false).maxAge(3600);
  24. }
  25. };
  26. }
  27. }

三、过滤器实现跨域 Filter based CORS support

  1. @Configuration
  2. public class MyConfiguration {
  3. @Bean
  4. public FilterRegistrationBean corsFilter() {
  5. UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
  6. CorsConfiguration config = new CorsConfiguration();
  7. config.setAllowCredentials(false);
  8. config.addAllowedOrigin("http://domain.com");
  9. config.addAllowedHeader("*");
  10. config.addAllowedMethod("*");
  11. source.registerCorsConfiguration("/**", config);
  12. FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
  13. bean.setOrder(0);
  14. return bean;
  15. }
  16. }
原文:https://blog.csdn.net/saytime/article/details/74937204
相关标签: 跨域