Vue+Springboot项目,前后端分离项目加密传输

第一个项目

项目描述:通过RSA对前后端传输的数据进行加密解密,前端通过公钥进行加密,Java后端通过私钥进行解密。

薛雄辉/springbootdemo - Gitee.com

Java后端



	4.0.0

	com.demo
	rsa
	0.0.1-SNAPSHOT
	jar

	rsa
	java与node.js非对称加密

	
		org.springframework.boot
		spring-boot-starter-parent
		2.0.4.RELEASE
		 
	

	
		UTF-8
		UTF-8
		1.8
	

	
		
			org.springframework.boot
			spring-boot-starter-web
		

		
			org.springframework.boot
			spring-boot-devtools
			runtime
		
		
			org.springframework.boot
			spring-boot-starter-test
			test
		

		
		
			org.bouncycastle
			bcpkix-jdk15on
			1.60
		

	

	
		
			
				org.springframework.boot
				spring-boot-maven-plugin
			
		
	



控制层

package com.demo.rsa;

import java.io.StringWriter;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.Security;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

import javax.crypto.Cipher;

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemWriter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * java前后端分离非对称加密数据传输
 *
 */
@RestController
public class MainController {

	/**
	 * 存储用户信息
	 */
	private Map users = new ConcurrentHashMap<>();

	/**
	 * 存储session私钥
	 */
	private Map session = new ConcurrentHashMap<>();

	static {
		Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
	}

	/**
	 * 根据token获取用户的信息
	 * @param token
	 * @return
	 */
	@GetMapping("getUser")
	public String getUser(@RequestHeader(value = "Authorization", required = false) String token) {
		if (token == null) {
			return null;
		}
		return users.containsKey(token) ? users.get(token) : null;
	}

	/**
	 * 账号密码明文传输登陆
	 * @Deprecated 这个注解表示这个方法不推荐程序员使用,但是还可以使用
	 * @param params
	 * @return
	 */
	@PostMapping("login")
	@Deprecated
	public Map login(@RequestBody Map params) {
		Map result = new HashMap<>();
		if (!params.containsKey("account") || !params.containsKey("password")) {
			result.put("success", false);
			result.put("message", "请输入账号和密码");
			return result;
		}
		if (!"123456".equals(params.get("password"))) {
			result.put("success", false);
			result.put("message", "密码错误");
			return result;
		}

		String token = UUID.randomUUID().toString();
		users.put(token, params.get("account"));

		result.put("success", true);
		result.put("message", "登录成功");
		result.put("data", token);
		return result;
	}

	/**
	 * 获取session公钥
	 * 
	 * @return
	 */
	@GetMapping("getSession")
	public Map getSession() throws Exception {
		String sessionId = UUID.randomUUID().toString();
		Map result = new HashMap<>();
		result.put("sessionId", sessionId);

		String algorithm = "RSA";
		String privateKey = null, publicKey = null;

		KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(algorithm);
		keyPairGen.initialize(512);
		KeyPair keyPair = keyPairGen.generateKeyPair();

		byte[] encoded = keyPair.getPrivate().getEncoded();
		PrivateKeyInfo pkInfo = PrivateKeyInfo.getInstance(encoded);
		ASN1Encodable encodable = pkInfo.parsePrivateKey();
		ASN1Primitive primitive = encodable.toASN1Primitive();
		byte[] privateKeyPKCS1 = primitive.getEncoded();
		PemObject pemObject = new PemObject("RSA PRIVATE KEY", privateKeyPKCS1);
		try (StringWriter stringWriter = new StringWriter()) {
			try (PemWriter pemWriter = new PemWriter(stringWriter)) {
				pemWriter.writeObject(pemObject);
				pemWriter.flush();
				String pemString = stringWriter.toString();
				privateKey = pemString;
			}
		}

		encoded = keyPair.getPublic().getEncoded();
		SubjectPublicKeyInfo spkInfo = SubjectPublicKeyInfo.getInstance(encoded);
		primitive = spkInfo.parsePublicKey();
		byte[] publicKeyPKCS1 = primitive.getEncoded();

		pemObject = new PemObject("RSA PUBLIC KEY", publicKeyPKCS1);
		try (StringWriter stringWriter = new StringWriter()) {
			try (PemWriter pemWriter = new PemWriter(stringWriter)) {
				pemWriter.writeObject(pemObject);
				pemWriter.flush();
				String pemString = stringWriter.toString();
				publicKey = pemString;
			}
		}

		// 记录私钥
		session.put(sessionId, privateKey);
		// 返回公钥
		result.put("publicKey", publicKey);

		return result;
	}

	/**
	 * 加密后的前端数据进行登陆
	 * @param params
	 * @return
	 */
	@SuppressWarnings("unchecked")
	@PostMapping("loginByEncrypt")
	public Map loginByEncrypt(@RequestBody Map params) {
		Map result = new HashMap<>();

		if (!params.containsKey("sessionId")) {
			result.put("success", false);
			result.put("message", "sessionId是必填参数");
			return result;
		}

		if (!params.containsKey("playload")) {
			result.put("success", false);
			result.put("message", "playload是必填参数");
			return result;
		}

		String sessionId = params.get("sessionId");

		if (!session.containsKey(sessionId)) {
			result.put("success", false);
			result.put("message", "无效session");
			return result;
		}

		Map json = null;
		try {
			String privateKey = session.get(sessionId);
			String playload = params.get("playload");
			String text = decrypt(playload, privateKey);

			ObjectMapper mapper = new ObjectMapper();
			json = mapper.readValue(text, Map.class);
		} catch (Exception e) {
			e.printStackTrace();
		}

		if (json == null) {
			result.put("success", false);
			result.put("message", "非法请求");
			return result;
		}

		if (!json.containsKey("account") || !json.containsKey("password")) {
			result.put("success", false);
			result.put("message", "请输入账号和密码");
			return result;
		}
		if (!"123456".equals(json.get("password"))) {
			result.put("success", false);
			result.put("message", "密码错误");
			return result;
		}

		String token = UUID.randomUUID().toString();
		users.put(token, json.get("account"));

		result.put("success", true);
		result.put("message", "登录成功");
		result.put("data", token);
		return result;
	}

	/**
	 * 私钥解密
	 * 
	 * @param text
	 * @param privateKey
	 * @return
	 * @throws Exception
	 */
	private String decrypt(String text, String privateKey) throws Exception {
		String algorithm = "RSA";
		String keyText = privateKey.split("-----")[2].replaceAll("\n", "").replaceAll("\r", "");
		byte[] bytes = Base64.decode(keyText.getBytes());
		KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
		PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(bytes);
		PrivateKey key = keyFactory.generatePrivate(privateKeySpec);

		Cipher cipher = Cipher.getInstance(algorithm);
		cipher.init(Cipher.DECRYPT_MODE, key);

		byte[] doFinal = cipher.doFinal(Base64.decode(text));
		return new String(doFinal, "utf-8");
	}
}

Vue前端

使用Vue脚手架搭建项目

vue init webpack demo-rsa
npm install
npm install --save axios

main.js

import Vue from 'vue'
import App from './App'
import router from './router'

Vue.config.productionTip = false

import axios from 'axios'
Vue.prototype.$axios = axios
axios.defaults.baseURL = '/api'

new Vue({
  el: '#app',
  router,
  components: {
    App
  },
  template: ''
})

路由配置文件

import Vue from 'vue'
import Router from 'vue-router'
import Main from '@/components/Main'
import Login from '@/components/Login'

Vue.use(Router)
let routes = [{
    path: '/',
    name: '首页',
    component: Main
  },
  {
    path: '/login',
    name: '登录',
    component: Login
  }
]

const router = new Router({
  routes: routes
})

router.beforeEach((to, from, next) => {
  if (to.path == '/login') {
    sessionStorage.removeItem('Authorization')
  }

  let token = sessionStorage.getItem('Authorization')
  if (!token && to.path != '/login') {
    next({
      path: '/login'
    })
    return
  }
  next()
})

export default router;

router/index.js

登录页





登录后的页面








components/Main.vue

设置开发跨域

Vue+Springboot项目,前后端分离项目加密传输_第1张图片

 proxyTable: {
      '/api': {
        target: 'http://localhost:8080/',
        changeOrigin: true,
        pathRewrite: {
          '^/api': '/'
        }
      }
    }

第二个项目:前后端都加密的解决方案

前后端RSA互相加解密、加签验签、密钥对生成(Java)_前后端rsa加解密_凌波漫步&的博客-CSDN博客

你可能感兴趣的:(vue.js,spring,boot,加解密)