feat: 前端添加rsa非对称加密策略

This commit is contained in:
fit2cloud-chenyw 2021-02-19 14:34:46 +08:00
parent 4df9280fe8
commit 60c525d2f4
9 changed files with 183 additions and 22 deletions

View File

@ -1,11 +1,14 @@
package com.fit2cloud.commons.auth.api;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.asymmetric.RSA;
import com.fit2cloud.commons.auth.bean.LoginDto;
import com.fit2cloud.commons.auth.bean.UserBean;
import com.fit2cloud.commons.auth.bean.UserInfo;
import com.fit2cloud.commons.auth.config.RsaProperties;
import com.fit2cloud.commons.auth.service.UserService;
import com.fit2cloud.commons.auth.util.JWTUtil;
import com.fit2cloud.commons.auth.util.RsaUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
@ -23,18 +26,21 @@ public class UserApi {
private UserService userService;
@PostMapping("/login")
public Map<String, Object> login(@RequestBody LoginDto loginDto){
public Map<String, Object> login(@RequestBody LoginDto loginDto) throws Exception{
String username = loginDto.getUsername();
String password = loginDto.getPassword();
String realPwd = userService.getPassword(username);
if (StrUtil.isEmpty(realPwd)){
throw new RuntimeException("没有该用户!");
}
if (!StrUtil.equals(realPwd, password)){
String pwd = RsaUtil.decryptByPrivateKey(RsaProperties.privateKey, password);
String realpwd = RsaUtil.decryptByPrivateKey(RsaProperties.privateKey, realPwd);
if (!StrUtil.equals(pwd, realpwd)){
throw new RuntimeException("密码错误!");
}
Map<String,Object> result = new HashMap<>();
result.put("token", JWTUtil.sign(username, password));
result.put("token", JWTUtil.sign(username, realpwd));
return result;
}

View File

@ -0,0 +1,17 @@
package com.fit2cloud.commons.auth.config;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Data
@Component
public class RsaProperties {
public static String privateKey;
@Value("${rsa.private_key}")
public void setPrivateKey(String privateKey) {
RsaProperties.privateKey = privateKey;
}
}

View File

@ -3,6 +3,7 @@ package com.fit2cloud.commons.auth.dao;
import com.fit2cloud.commons.auth.bean.ExtPermissionBean;
import com.fit2cloud.commons.auth.entity.SysUser;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@ -11,20 +12,23 @@ import java.util.List;
@Mapper
public interface ExtUserMapper {
@Select("select password from sys_user where user_id = #{userId,jdbcType=VARCHAR} ")
String getPassword(String userId);
@Select("select password from sys_user where username = #{userName,jdbcType=VARCHAR} ")
String getPassword(String userName);
@Select("select role_id from sys_users_roles where user_id = #{userId,jdbcType=VARCHAR} ")
List<String> getRole(String userId);
@Select("select role_id from sys_users_roles where username = #{userName,jdbcType=VARCHAR} ")
List<String> getRole(String userName);
@Select({
"select sm.permission ",
"from sys_users_roles sur ",
"LEFT JOIN sys_roles_menus srm on srm.role_id = sur.role_id ",
"LEFT JOIN sys_menu sm on sm.menu_id = srm.menu_id ",
"where sur.user_id = #{userId,jdbcType=VARCHAR} "
"where sur.username = #{userName,jdbcType=VARCHAR} "
})
List<String> getPermission(String userId);
List<String> getPermission(String userName);
@Select("select * from sys_user where username = #{username,jdbcType=VARCHAR}")
SysUser getUser(String username);
@Select("select path,permission from sys_menu where path is not null")
List<ExtPermissionBean> getPermissions();

View File

@ -3,6 +3,7 @@ package com.fit2cloud.commons.auth.service;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fit2cloud.commons.auth.bean.UserBean;
import com.fit2cloud.commons.auth.dao.ExtUserMapper;
import com.fit2cloud.commons.auth.entity.SysUser;
@ -21,7 +22,8 @@ public class UserService {
@Autowired(required = false)
private SysUserMapper sysUserMapper;
public UserBean getUser(String username){
SysUser sysUser = sysUserMapper.selectById(username);
SysUser sysUser = extUserMapper.getUser(username);
if (ObjectUtil.isNull(sysUser))return null;
String password = sysUser.getPassword();

View File

@ -0,0 +1,131 @@
package com.fit2cloud.commons.auth.util;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
public class RsaUtil {
/**
* 公钥解密
*
* @param publicKeyText 公钥
* @param text 待解密的信息
* @return /
* @throws Exception /
*/
public static String decryptByPublicKey(String publicKeyText, String text) throws Exception {
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
byte[] result = cipher.doFinal(Base64.decodeBase64(text));
return new String(result);
}
/**
* 私钥加密
*
* @param privateKeyText 私钥
* @param text 待加密的信息
* @return /
* @throws Exception /
*/
public static String encryptByPrivateKey(String privateKeyText, String text) throws Exception {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] result = cipher.doFinal(text.getBytes());
return Base64.encodeBase64String(result);
}
/**
* 私钥解密
*
* @param privateKeyText 私钥
* @param text 待解密的文本
* @return /
* @throws Exception /
*/
public static String decryptByPrivateKey(String privateKeyText, String text) throws Exception {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] result = cipher.doFinal(Base64.decodeBase64(text));
return new String(result);
}
/**
* 公钥加密
*
* @param publicKeyText 公钥
* @param text 待加密的文本
* @return /
*/
public static String encryptByPublicKey(String publicKeyText, String text) throws Exception {
X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] result = cipher.doFinal(text.getBytes());
return Base64.encodeBase64String(result);
}
/**
* 构建RSA密钥对
*
* @return /
* @throws NoSuchAlgorithmException /
*/
public static RsaKeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());
String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
return new RsaKeyPair(publicKeyString, privateKeyString);
}
/**
* RSA密钥对对象
*/
public static class RsaKeyPair {
private final String publicKey;
private final String privateKey;
public RsaKeyPair(String publicKey, String privateKey) {
this.publicKey = publicKey;
this.privateKey = privateKey;
}
public String getPublicKey() {
return publicKey;
}
public String getPrivateKey() {
return privateKey;
}
}
}

View File

@ -1,2 +1,2 @@
spring.cache.type=ehcache
spring.cache.ehcache.config=ehcache.xml
spring.cache.ehcache.config=ehcache.xml

View File

@ -22,7 +22,8 @@
"nprogress": "^0.2.0",
"vue": "^2.6.11",
"vue-i18n": "^8.22.4",
"vuex": "^3.6.0"
"vuex": "^3.6.0",
"jsencrypt": "^3.0.0-rc.1"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",

View File

@ -2,19 +2,19 @@
import {get, post, put} from "@/plugins/request"
export function login(data) {
return post("/samples/user-token/login", data)
return post("/login", data)
}
export function logout() {
return post("/samples/user-token/logout")
return post("/logout")
}
export function getCurrentUser() {
return get("/samples/user-token/current")
return get("/info")
}
export function updateInfo(data) {
return put("/samples/user-token/update", data)
return put("/update", data)
}

View File

@ -1,6 +1,7 @@
import router from './router'
import store from './store'
import NProgress from 'nprogress'
import { getToken } from '@/utils/token'
import 'nprogress/nprogress.css'
NProgress.configure({showSpinner: false}) // NProgress Configuration
@ -13,12 +14,12 @@ const generateRoutes = async (to, from, next) => {
next()
} else {
try {
const {roles} = await store.dispatch('user/getCurrentUser')
const {roles} = await store.dispatch('user-token/getCurrentUser')
const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
router.addRoutes(accessRoutes)
next({...to, replace: true})
} catch (error) {
await store.dispatch('user/logout')
await store.dispatch('user-token/logout')
next(`/login?redirect=${to.path}`)
NProgress.done()
}
@ -28,10 +29,9 @@ const generateRoutes = async (to, from, next) => {
// 路由前置钩子,根据实际需求修改
router.beforeEach(async (to, from, next) => {
NProgress.start()
const isLogin = await store.dispatch('user/isLogin') // 或者user-token/isLogin
if (isLogin) {
// const isLogin = await store.dispatch('user-token/isLogin') // 或者user-token/isLogin
const hasToken = getToken()
if (hasToken) {
if (to.path === '/login') {
next({path: '/'})
NProgress.done()