devtool+jasypt+springBoot 初战演练
前言
新手学习还真是痛苦啊~尝试将jasypt中的秘钥由用户输入
简介
devtool是springboot的热部署工具
jasypt是密码Digest认证,文本和对象加密,集成hibernate,Spring Security(Acegi)来增强密码管理
所用IDE: intellji IDEA
1.创建pom.xml
spring boot框架
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <name>demo</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <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-configuration-processor</artifactId> <version>1.5.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jasper</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <version>8.5.20</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency> <dependency> <groupId>org.jasypt</groupId> <artifactId>jasypt-spring31</artifactId> <version>1.9.1</version> </dependency> <!--jstl--> <!--environment--> <!--other template--> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2.Controller
package com.controller; import com.entity.springTest; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.env.EnvironmentPostProcessor; import org.springframework.boot.env.PropertySourceLoader; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.core.env.*; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import java.io.*; import java.util.ArrayList; import java.util.List; import java.util.Properties; @Controller public class JspController implements EnvironmentPostProcessor { private Properties prop=new Properties(); private springTest springtest; private springTest springtest1; @Value("${app.myUrl}") private String myUrlGlobal; @Value("${app.myPassword:defaultvalue}") private String myPasswordGlobal; @Value("app.ftpUserName") private String ftpUserNameGlobal; @Value("app.ftpPath") private String ftpPathGlobal; private StandardPBEStringEncryptor stringEncryptor; private StandardPBEStringEncryptor stringEncryptor1; @Autowired private Environment env; @Autowired private ConfigurableEnvironment environment; @Autowired private ApplicationContext ctx; private FileOutputStream fileOutputStream; private InputStream fileInputStream; private InputStream targetFileInputStream; private FileOutputStream targeTFileOutputStream; private String result; private String passwordResult; private String ftpUserNameResult; private String ftpPathResult; private PropertySourceLoader loader; private static String KEY=""; private static String keyValue; @RequestMapping("/inputCipher") public ModelAndView inputCipher(String cipher){ //将秘钥存入全局变量 this.KEY=cipher; try { //读入资源目录下的application.properties 文件 fileInputStream=new BufferedInputStream(new FileInputStream("./src/main/resources/application.properties")); prop=new Properties(); prop.load(fileInputStream); //将properties的值读入到springtest 然后返回页面 springtest=new springTest(); springtest.setMyUrl(prop.getProperty("app.myUrl")); springtest.setMyPassword(prop.getProperty("app.myPassword")); springtest.setFtpPath(prop.getProperty("app.ftpPath")); springtest.setFtpUserName(prop.getProperty("app.ftpUserName")); springtest.setSignal("already entered"); //将文件关闭 fileInputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return new ModelAndView("index","springtest",springtest); } //解密action @RequestMapping("/encrpt") public ModelAndView encrypt(String Encrpt, String passwordEncrpt, HttpServletRequest request, String ftpUserName, String ftpPath) { try { //如果点击的是解密按钮,返回解密输入key值页面 if(request.getParameter("Button").equals("decrypt")){ return new ModelAndView("testKey"); } if(KEY.isEmpty()&&request.getParameter("Button").equals("encrypt")){ //如果key值为空或者key值是空字符串,返回到输入key值的jsp页面 springtest=new springTest(); springtest.setSignal("Please type into the password"); return new ModelAndView("inputCipherCode","springtest",springtest); }else{ springtest.setSignal("Already Entered"); } stringEncryptor=new StandardPBEStringEncryptor(); stringEncryptor.setPassword(KEY); //读出数据 fileInputStream=new BufferedInputStream( new FileInputStream("./src/main/resources/application.properties")); prop.load(fileInputStream); //得到资源目录下的property里面的值 String value=prop.getProperty("app.myUrl"); String passwordValue=prop.getProperty("app.myPassword"); String ftpUserNameValue=prop.getProperty("app.ftpUserName"); String ftpPathValue=prop.getProperty("app.ftpPath"); //判断前台传入值是否为空或为空的字符串,为空则写入applicaiton.properties里面的默认值进行加密 if(!(Encrpt==null)&&!(Encrpt=="")){ value=Encrpt; } if(!(passwordEncrpt==null)&&!(passwordEncrpt=="")){ passwordValue=Encrpt; } if(!(ftpUserName==null)&&!(ftpUserName=="")){ ftpUserNameValue=ftpUserName; } if(!(ftpPath==null)&&!(ftpPath=="")){ ftpPathValue=ftpPath; } //加密数据,变量名后缀是result的为加密过后的字符串 result=stringEncryptor.encrypt(value); passwordResult=stringEncryptor.encrypt(passwordValue); ftpUserNameResult=stringEncryptor.encrypt(ftpUserNameValue); ftpPathResult=stringEncryptor.encrypt(ftpPathValue); fileOutputStream = new FileOutputStream("./src/main/resources/application.properties", false); //给加密完的数据套入ENC(),方便@value解密 result="ENC("+result+")"; passwordResult="ENC("+passwordResult+")"; ftpUserNameResult="ENC("+ftpUserNameResult+")"; ftpPathResult="ENC("+ftpPathResult+")"; //存入properties的文件中 prop.setProperty("app.myUrl",result); prop.setProperty("app.myPassword",passwordResult); prop.setProperty("app.ftpUserName",ftpUserNameResult); prop.setProperty("app.ftpPath",ftpPathResult); prop.setProperty("jasypt.encryptor.password",KEY); //写入properties数据 prop.store(fileOutputStream,"Success"); fileInputStream.close(); fileOutputStream.close(); //改变环境变量中的值 changeStandardEnvironment(); //通过class文件改写properties changePropertiesInTarget(KEY); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } //写入到springtest的这个entity中,通过ModelAndView返回到页面 springtest=new springTest(); springtest.setMyUrl(""+result); springtest.setMyPassword(""+passwordResult); springtest.setFtpPath(ftpPathResult); springtest.setFtpUserName(ftpUserNameResult); springtest.setSignal("success"); if(!KEY.isEmpty()){ springtest.setSignal("Already Entered"); } return new ModelAndView("index","springtest",springtest); } //输入解析秘钥 @RequestMapping("/decryptKey") public ModelAndView decryptValue(String decrypt){ this.keyValue=decrypt; //判断前后输入key值是否一致 if(keyValue.equals(env.getProperty("jasypt.encryptor.password"))) { //使用StandardPBEStringEncryptor 的算法进行解密 stringEncryptor1=new StandardPBEStringEncryptor(); stringEncryptor1.setPassword(keyValue); try { //读入解密信息 fileInputStream=new BufferedInputStream(new FileInputStream("./src/main/resources/application.properties")); prop=new Properties(); prop.load(fileInputStream); String myurl=prop.getProperty("app.myUrl"); String mypassword=prop.getProperty("app.myPassword"); String ftpUserName=prop.getProperty("app.ftpUserName"); String ftpPath=prop.getProperty("app.ftpPath"); //进行裁剪 myurl=myurl.substring(4,myurl.length()-1); mypassword=mypassword.substring(4,mypassword.length()-1); ftpUserName=ftpUserName.substring(4,ftpUserName.length()-1); ftpPath=ftpPath.substring(4,ftpPath.length()-1); //进行解密并放入到springtest中 springtest=new springTest(); springtest.setMyUrl(stringEncryptor1.decrypt(myurl)); springtest.setMyPassword(stringEncryptor1.decrypt(mypassword)); springtest.setFtpUserName(stringEncryptor1.decrypt(ftpUserName)); springtest.setFtpPath(stringEncryptor1.decrypt(ftpPath)); fileInputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }else{ //如果前后密码不匹配报错 throw new RuntimeException("The key word must be similar"); } return new ModelAndView("index","springtest",springtest); } @RequestMapping("/") public ModelAndView all() { try { //读取资源目录下的文件,返回到index页面 fileInputStream=new BufferedInputStream(new FileInputStream("./src/main/resources/application.properties")); prop=new Properties(); prop.load(fileInputStream); springtest=new springTest(); springtest.setMyUrl(prop.getProperty("app.myUrl")); springtest.setMyPassword(prop.getProperty("app.myPassword")); springtest.setFtpUserName(prop.getProperty("app.ftpUserName")); springtest.setFtpPath(prop.getProperty("app.ftpPath")); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return new ModelAndView("index","springtest",springtest); } //读写environment和value 标注的值 @GetMapping(path = "/show") public ModelAndView showValueFromEnvironmentAndValueAnnotation(String decrypt){ String test1; String test2; if(!(decrypt.equals(env.getProperty("jasypt.encryptor.password")))){ String name="the key word is not same, please reenter"; return new ModelAndView("decryptKey","name",name); } List<springTest> list=new ArrayList<springTest>(); springtest=new springTest(); springtest.setMyUrl("get from value annotation "+myUrlGlobal); springtest.setMyPassword("get from value annotation "+myPasswordGlobal); list.add(springtest); springtest1=new springTest(); test1=env.getProperty("app.myUrl"); springtest1.setMyUrl("get from environment "+test1); test2=env.getProperty("app.myPassword"); springtest1.setMyPassword("get from environment "+test2); list.add(springtest1); return new ModelAndView("show","list",list); } //替换environment中的properties文件 @Bean public String changeStandardEnvironment(){ Properties prop=new Properties(); try { InputStream fileInputStream=new BufferedInputStream( new FileInputStream("./src/main/resources/application.properties")); prop.load(fileInputStream); String value=prop.getProperty("app.myUrl"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } StandardEnvironment env=ctx.getBean(StandardEnvironment.class); env.getPropertySources().replace("applicationConfig: [classpath:/application.properties]",new PropertiesPropertySource("applicationConfig: [classpath:/application.properties]",prop)); return "newbee"; } //通过应用getclass的值修改编译目录下的properties文件,未完成,只做了读取 @Bean public String changePropertiesByClass(){ Properties properties; properties=new Properties(); Class clazz=JspController.class; InputStream in=clazz.getResourceAsStream("/application.properties"); try { properties.load(in); System.out.println("change properties by class"+properties.getProperty("app.myUrl")); System.out.println("change properties by class"+properties.getProperty("app.myPassword")); } catch (IOException e) { e.printStackTrace(); } return "Success"; } //通过重写postProcessEnvironment改变环境变量中的properties值,未完成 @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { Resource path=new ClassPathResource("./src/main/resources/application.properties"); PropertySource<?> propertySource=loadProperties(path); environment.getPropertySources().addLast(propertySource); System.out.println("===================================enter"); } //返回properties 的值 private PropertySource<?> loadProperties(Resource path){ if (!path.exists()) { throw new IllegalArgumentException("Resource " + path + " does not exist"); } try { return this.loader.load("custom-resource",path).get(0); } catch (IOException ex) { throw new IllegalStateException( "Failed to load yaml configuration from " + path, ex); } } //通过file的读入读出改变编辑目录下中的properties的值 private Boolean changePropertiesInTarget(String KEY1){ Properties properties=new Properties(); Properties properties1=new Properties(); try { InputStream inProperties=new BufferedInputStream(new FileInputStream("./src/main/resources/application.properties")); properties.load(inProperties); FileOutputStream outproperties=new FileOutputStream("./target/classes/application.properties",false); properties1.setProperty("app.myUrl",properties.getProperty("app.myUrl")); properties1.setProperty("app.myPassword",properties.getProperty("app.myPassword")); properties1.setProperty("spring.mvc.view.suffix",properties.getProperty("spring.mvc.view.suffix")); properties1.setProperty("app.ftpUserName",properties.getProperty("app.ftpUserName")); properties1.setProperty("jasypt.encryptor.password",KEY1); properties1.setProperty("server.port",properties.getProperty("server.port")); properties1.setProperty("app.ftpPath",properties.getProperty("app.ftpPath")); properties1.setProperty("server.servlet.context-path",properties.getProperty("server.servlet.context-path")); properties1.store(outproperties,"prepared"); inProperties.close(); outproperties.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return true; } }
3.Properties 文件属性
app.myPassword=give server.servlet.context-path=/ency app.ftpPath=/pub/here server.port=7979 spring.mvc.view.prefix=/META-INF/views/ jasypt.encryptor.password=654321 app.ftpUserName=admin app.myUrl=ftp://192.108.0.1:9090 spring.mvc.view.suffix=.jsp
4.文件目录