CORS跨域资源共享
哪些操作不受同源限制
哪些操作受到同源限制
- 在浏览器中发起一个AJAX请求,会受到同源策略限制。
使用CORS解决同源限制
-
@CrossOrigin注解(在需要跨域访问的controller上加上@CrossOrigin则该controller就可以进行跨域访问了)
@RestController
@RequestMapping("demos")
@CrossOrigin
public class DemoController {
@GetMapping
public String demos() {
System.out.println("========demo=======");
return "demo ok";
}
}
-
全局解决跨域问题 package com.baizhi.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
source.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(source);
}
}
在进行前后端分离开发时,前端部署在一台服务器上,这台服务器有它自己的域名,有它自己的ip,后端系统也有自己的域名,也有自己的ip,前端和后端属于不同的源,而前端和后端是通过ajax进行通信的,ajax不能在不同源之间通信,为了解决ajax不能跨域访问,就有了CORS的产生,CORS是专门解决ajax不能跨域访问的问题的。
接下来我们来进行测试
用到的包结构
- 因为要用到themeleaf,所以需要导入themeleaf依赖并在application.yml中进行配置
我们使用themeleaf,所以要导入themeleaf依赖,并且在配置文件中配置一下themeleaf的模板目录和模板后缀
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
application.yml
spring:
thymeleaf:
prefix: classpath:/templates/
suffix: .html
cache: false
- 创建cors.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
function test(){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function (){
if(xhr.status == 200 && xhr.readyState == 4){
console.log(xhr.responseText);
document.getElementById("msg").innerText = "返回的结果为: " + xhr.responseText;
}
}
xhr.open("GET", "http://localhost:8080/demos");
xhr.send();
}
</script>
</head>
<body>
<h1>cors 跨域测试</h1>
<input type="button" value="点我发送ajax请求" onclick="test()">
<h4 id="msg"></h4>
</body>
</html>
- 创建controller
@RestController
@RequestMapping("demos")
public class DemoController {
@GetMapping
public ResponseEntity<String> demo(){
System.out.println("demo ok");
return new ResponseEntity<>("demook", HttpStatus.OK);
}
@GetMapping("/{id}")
public ResponseEntity<String> demo1(@PathVariable("id") Integer id){
System.out.println("demo ok " + id);
if(id < 0) throw new IllegalNumberException("无效id,请检查!");
return new ResponseEntity<>("demo ok", HttpStatus.OK);
}
}
- 进行跨域访问
- 解决方案
package com.baizhi.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
source.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(source);
}
}
在使用全局解决方案时导包时需要注意不要导错包啦
注:全局解决方案和局部解决方案使用一个即可,两个都使用又会产生新的问题
- 使用解决方案之后
Jasypt加密
引言
Jasypt 也即Java Simplified Encryption是Sourceforge.net上的一个开源项目。在当地时间11月23号的通告中,Jasypt 1.4的新特征包括:加密属性文件(encryptable properties files)、Spring Framework集成、加密Hibernate数据源配置、新的命令行工具、URL加密的Apache wicket集成以及升级文档。
根据Jasypt文档,该技术可用于加密任务与应用程序,例如加密密码、敏感信息和数据通信、创建完整检查数据的sums. 其他性能包括高安全性、基于标准的加密技术、可同时单向和双向加密的加密密码、文本、数字和二进制文件。Jasypt也可以与Acegi Security整合也即Spring Security。Jasypt亦拥有加密应用配置的集成功能,而且提供一个开放的API从而任何一个Java Cryptography Extension都可以使用Jasypt。
Jasypt还符合RSA标准的基于密码的加密,并提供了无配置加密工具以及新的、高可配置标准的加密工具。
Jasypt加密时需要交给其一个秘钥,然后配置一下秘钥,之后将需要加密的字符串交给stringEncryptor类的方法进行加密,根据加密之后得到的加密字符串和秘钥还可以由stringEncryptor方法进行解密,解密之后的字符串就是我们加密之后的字符串对应的原字符串,所以这个秘钥是很重要的,如果让别人知道了这个秘钥,那么Jasypt加密就没有任何的意义了,这个秘钥可以是任何字符串,我们一定不能让其他人知道这个秘钥。
另外,使用Jasypt对于同一个字符串和相同的秘钥进行多次加密得到的字符串不同,但是使用相同的秘钥和这些不同的字符串进行解密得到的原串是一样的,也就是说,我们可以取这些加密之后的字符串中的任意一个作为加密之后的串,无论如果,解密之后的串一定是原串。
使用Jasypt进行加密的步骤:
我们在实际开发中演示一下如何使用Jasypt进行加密
用到的包结构
- 先在JVM参数中配置秘钥,stringEncryptor类的方法对需要加密的字符串进行加密操作,得到加密串
配置秘钥
秘钥可以是任意字符串,我们将秘钥设置为 cf150b74e4824146ad76e9ebe757ba76
之后设置JVM参数
-Djasypt.encryptor.password=cf150b74e4824146ad76e9ebe757ba76
注意:在运行的时候一定要设置这个VM参数
之后利用测试方法获得对想要加密的字符串加密之后的加密串,比如说现在我们想要对 “root” 和 “localhost” 这两个字符串进行加密:
注:使用stringEncryptor类需要引入Jasypt依赖
得到对 “root” 加密之后的加密串:BSxdC2iO2COX+4v7LYuL8w==
得到对 “localhost” 加密之后的加密串: BZEUji+svih5BuEopXMLWLvceWS5reTc
- 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
注意:使用Jasypt进行加密需要引入Jasypt依赖
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
- 编写配置文件
我们对 “root” 字符串进行了加密,也就是对username、password加密
spring:
thymeleaf:
prefix: classpath:/templates/
suffix: .html
cache: false
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://hocalhost:3306/ems-jsp?characterEncoding=UTF-8
username: ENC(BSxdC2iO2COX+4v7LYuL8w==)
password: ENC(BSxdC2iO2COX+4v7LYuL8w==)
mybatis:
mapper-locations: classpath:com/baizhi/mapper/*.xml
type-aliases-package: com.baizhi.eneity
jasypt:
encryptor:
algorithm: PBEWithMD5AndDES
注:在编写配置文件时别忘了在入口类上加上 @MapperScan(“com.baizhi.dao”) 扫描dao接口所在的包,在工厂中创建dao接口的对象
@SpringBootApplication
@MapperScan("com.baizhi.dao")
public class SpringbootDay10Application {
public static void main(String[] args) {
SpringApplication.run(SpringbootDay10Application.class, args);
}
}
- 创建Dao接口
public interface UserDao {
List<User> findAll();
}
- 编写mapper配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.baizhi.dao.UserDao">
<select id="findAll" resultType="com.baizhi.eneity.User">
select id, username, realname, password, gender from `user`
</select>
</mapper>
- 创建service接口
public interface UserService {
List<User> findAll();
}
- 创建service接口实现类
@Service
@Transactional
public class UserServiceImpl implements UserService{
private UserDao userDao;
@Autowired
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
@Override
public List<User> findAll() {
return userDao.findAll();
}
}
- 创建controller
@RestController
@RequestMapping("users")
public class UserController {
private UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping
public ResponseEntity<List<User>> users(){
List<User> users = userService.findAll();
return new ResponseEntity<List<User>>(users, HttpStatus.OK);
}
}
- 运行测试
注:在运行入口类时一定要配置VM参数,为的是设置秘钥,在本次测试中需要设置VM参数
-Djasypt.encryptor.password=cf150b74e4824146ad76e9ebe757ba76
总结:
使用Jasypt进行加密可以很好地避免明文密码泄露问题,但是Jasypt加密最重要的秘钥,所以我们自己的秘钥一定不能泄露出去。
|