天天看點

JavaWeb RSA密碼加密登入

思路:每次登入前,向後端發送請求,由RSA生成一對公鑰和私鑰,用redis或者資料庫儲存使用者名對應的私鑰,擷取公鑰中的modulus和publicExponent,分别調用String#toString(int)方法,然後傳到前端,前端使用security.js加密密碼,然後進行登入,在後端使用私鑰解密,再驗證密碼的正确性。

注意:

  • 每次登入都需要擷取公鑰和私鑰
  • 保證每次登入時,生成的公鑰和私鑰與使用者名是對應的。
  • 1.在maven項目的pom.xml中添加下面的依賴,為了引入import org.bouncycastle.jce.provider.BouncyCastleProvider;作為安全服務提供者
<dependency>
			<groupId>org.bouncycastle</groupId>
			<artifactId>bcprov-jdk16</artifactId>
			<version>1.46</version>
		</dependency>
           
  • 2.RSAUtils工具類

    RSAUtils源碼:https://pan.baidu.com/s/1mkd2WWg

  • 3.Controller接口,為了驗證加密和解密的操作是否可行。(此接口要繞過攔截器)
/**
	 * 
	 * @Title: generateRSAKey 
	 * @Description: 生成公鑰和私鑰
	 * @param username
	 * @return  
	 * @date 2018年2月5日 下午4:25:05
	 * @author p7
	 */
	@ResponseBody
	@GetMapping(value = "/rsaKey/{username}")
	public ResultBean generateRSAKey(@PathVariable String username) {

		try {
			// 擷取公鑰和私鑰
			HashMap<String, Object> keys = RSAUtils.getKeys();
			RSAPublicKey publicKey = (RSAPublicKey) keys.get("public");
			RSAPrivateKey privateKey = (RSAPrivateKey) keys.get("private");
			// 儲存私鑰到 redis,也可以儲存到資料庫
			boolean res = redisService.set(username, privateKey);
			if (!res) {
				throw new BusinessLogicException("redis 儲存失敗");
			}
			// 将公鑰傳到前端
			Map<String,String> map = new HashMap<String,String>();
			// 注意傳回modulus和exponent以16為基數的BigInteger的字元串表示形式
			map.put("modulus", publicKey.getModulus().toString(16));
			map.put("exponent", publicKey.getPublicExponent().toString(16));
			
			return new ResultBean(map);
		} catch (NoSuchAlgorithmException e) {
			return new ResultBean(ResultBean.ERROR, e.getMessage());
		} catch (BusinessLogicException e) {
			return new ResultBean(ResultBean.ERROR, e.getMessage());
		}
	}

	/**
	 * 
	 * @Title: checkRSAKey 
	 * @Description: 驗證密碼
	 * @param username
	 * @param password
	 * @return  
	 * @date 2018年2月5日 下午4:25:43
	 * @author p7
	 */
	@ResponseBody
	@GetMapping(value = "/rsaKey/{username}/{password}")
	public ResultBean checkRSAKey(@PathVariable String username, @PathVariable String password) {
		Object object = redisService.get(username);
		try {
			// 解密
			String decryptByPrivateKey = RSAUtils.decryptByPrivateKey(password, (RSAPrivateKey) object);
			return new ResultBean(decryptByPrivateKey);
		} catch (Exception e) {
			return new ResultBean(ResultBean.ERROR, "解密失敗");
		}
	}
           
  • 4.在登入頁面引入security.js

    security.js:https://pan.baidu.com/s/1nxnArBN

  • 5.在登入的js中對接接口。
$(document).ready(function() {
	$(".loginBtn").click(function() {
		var uName = $(".userName").val(); //擷取使用者名
		var pWord = $(".passWord").val(); //擷取賬号
		// 擷取
		$.ajax({
			type:"get",
			url:userBasePath+"rsaKey/"+uName,
			success:function(data){
				console.log(data);
				var pwdKey = new RSAUtils.getKeyPair(data.data.exponent,"",data.data.modulus);
				var reversedPwd = pWord.split("").reverse().join("");
				var encrypedPwd = RSAUtils.encryptedString(pwdKey,reversedPwd);
				console.log(encrypedPwd);
				$.ajax({
					type:"get",
					url:userBasePath+"rsaKey/"+uName+"/"+encrypedPwd,
					success:function(data){
						console.log(data);
					},
					error: function(result, status, xhr) {
					}
				});
			},
			error: function(result, status, xhr) {
			}
		});
	}	
}	
           

繼續閱讀