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);
    }

    //读写environmentvalue 标注的值
   @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.文件目录

devtool+jasypt+springBoot 初战演练