forked from github/dataease
feat: 前端添加rsa非对称加密策略
This commit is contained in:
parent
4df9280fe8
commit
60c525d2f4
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,2 +1,2 @@
|
||||
spring.cache.type=ehcache
|
||||
spring.cache.ehcache.config=ehcache.xml
|
||||
spring.cache.ehcache.config=ehcache.xml
|
||||
|
@ -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",
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user