提交 60c525d2 authored 作者: fit2cloud-chenyw's avatar fit2cloud-chenyw

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

上级 4df9280f
package com.fit2cloud.commons.auth.api; package com.fit2cloud.commons.auth.api;
import cn.hutool.core.util.StrUtil; 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.LoginDto;
import com.fit2cloud.commons.auth.bean.UserBean; import com.fit2cloud.commons.auth.bean.UserBean;
import com.fit2cloud.commons.auth.bean.UserInfo; 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.service.UserService;
import com.fit2cloud.commons.auth.util.JWTUtil; import com.fit2cloud.commons.auth.util.JWTUtil;
import com.fit2cloud.commons.auth.util.RsaUtil;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.RequestContextHolder;
...@@ -23,18 +26,21 @@ public class UserApi { ...@@ -23,18 +26,21 @@ public class UserApi {
private UserService userService; private UserService userService;
@PostMapping("/login") @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 username = loginDto.getUsername();
String password = loginDto.getPassword(); String password = loginDto.getPassword();
String realPwd = userService.getPassword(username); String realPwd = userService.getPassword(username);
if (StrUtil.isEmpty(realPwd)){ if (StrUtil.isEmpty(realPwd)){
throw new RuntimeException("没有该用户!"); 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("密码错误!"); throw new RuntimeException("密码错误!");
} }
Map<String,Object> result = new HashMap<>(); Map<String,Object> result = new HashMap<>();
result.put("token", JWTUtil.sign(username, password)); result.put("token", JWTUtil.sign(username, realpwd));
return result; return result;
} }
......
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; ...@@ -3,6 +3,7 @@ package com.fit2cloud.commons.auth.dao;
import com.fit2cloud.commons.auth.bean.ExtPermissionBean; 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.Mapper;
import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Select;
...@@ -11,20 +12,23 @@ import java.util.List; ...@@ -11,20 +12,23 @@ import java.util.List;
@Mapper @Mapper
public interface ExtUserMapper { public interface ExtUserMapper {
@Select("select password from sys_user where user_id = #{userId,jdbcType=VARCHAR} ") @Select("select password from sys_user where username = #{userName,jdbcType=VARCHAR} ")
String getPassword(String userId); String getPassword(String userName);
@Select("select role_id from sys_users_roles where user_id = #{userId,jdbcType=VARCHAR} ") @Select("select role_id from sys_users_roles where username = #{userName,jdbcType=VARCHAR} ")
List<String> getRole(String userId); List<String> getRole(String userName);
@Select({ @Select({
"select sm.permission ", "select sm.permission ",
"from sys_users_roles sur ", "from sys_users_roles sur ",
"LEFT JOIN sys_roles_menus srm on srm.role_id = sur.role_id ", "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 ", "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") @Select("select path,permission from sys_menu where path is not null")
List<ExtPermissionBean> getPermissions(); List<ExtPermissionBean> getPermissions();
......
...@@ -3,6 +3,7 @@ package com.fit2cloud.commons.auth.service; ...@@ -3,6 +3,7 @@ package com.fit2cloud.commons.auth.service;
import cn.hutool.core.util.ObjectUtil; 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.bean.UserBean;
import com.fit2cloud.commons.auth.dao.ExtUserMapper; import com.fit2cloud.commons.auth.dao.ExtUserMapper;
import com.fit2cloud.commons.auth.entity.SysUser; import com.fit2cloud.commons.auth.entity.SysUser;
...@@ -21,7 +22,8 @@ public class UserService { ...@@ -21,7 +22,8 @@ public class UserService {
@Autowired(required = false) @Autowired(required = false)
private SysUserMapper sysUserMapper; private SysUserMapper sysUserMapper;
public UserBean getUser(String username){ public UserBean getUser(String username){
SysUser sysUser = sysUserMapper.selectById(username);
SysUser sysUser = extUserMapper.getUser(username);
if (ObjectUtil.isNull(sysUser))return null; if (ObjectUtil.isNull(sysUser))return null;
String password = sysUser.getPassword(); String password = sysUser.getPassword();
......
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;
}
}
}
spring.cache.type=ehcache spring.cache.type=ehcache
spring.cache.ehcache.config=ehcache.xml spring.cache.ehcache.config=ehcache.xml
\ No newline at end of file
...@@ -22,7 +22,8 @@ ...@@ -22,7 +22,8 @@
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"vue": "^2.6.11", "vue": "^2.6.11",
"vue-i18n": "^8.22.4", "vue-i18n": "^8.22.4",
"vuex": "^3.6.0" "vuex": "^3.6.0",
"jsencrypt": "^3.0.0-rc.1"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0", "@vue/cli-plugin-babel": "~4.5.0",
......
...@@ -2,19 +2,19 @@ ...@@ -2,19 +2,19 @@
import {get, post, put} from "@/plugins/request" import {get, post, put} from "@/plugins/request"
export function login(data) { export function login(data) {
return post("/samples/user-token/login", data) return post("/login", data)
} }
export function logout() { export function logout() {
return post("/samples/user-token/logout") return post("/logout")
} }
export function getCurrentUser() { export function getCurrentUser() {
return get("/samples/user-token/current") return get("/info")
} }
export function updateInfo(data) { export function updateInfo(data) {
return put("/samples/user-token/update", data) return put("/update", data)
} }
......
import router from './router' import router from './router'
import store from './store' import store from './store'
import NProgress from 'nprogress' import NProgress from 'nprogress'
import { getToken } from '@/utils/token'
import 'nprogress/nprogress.css' import 'nprogress/nprogress.css'
NProgress.configure({showSpinner: false}) // NProgress Configuration NProgress.configure({showSpinner: false}) // NProgress Configuration
...@@ -13,12 +14,12 @@ const generateRoutes = async (to, from, next) => { ...@@ -13,12 +14,12 @@ const generateRoutes = async (to, from, next) => {
next() next()
} else { } else {
try { try {
const {roles} = await store.dispatch('user/getCurrentUser') const {roles} = await store.dispatch('user-token/getCurrentUser')
const accessRoutes = await store.dispatch('permission/generateRoutes', roles) const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
router.addRoutes(accessRoutes) router.addRoutes(accessRoutes)
next({...to, replace: true}) next({...to, replace: true})
} catch (error) { } catch (error) {
await store.dispatch('user/logout') await store.dispatch('user-token/logout')
next(`/login?redirect=${to.path}`) next(`/login?redirect=${to.path}`)
NProgress.done() NProgress.done()
} }
...@@ -28,10 +29,9 @@ const generateRoutes = async (to, from, next) => { ...@@ -28,10 +29,9 @@ const generateRoutes = async (to, from, next) => {
// 路由前置钩子,根据实际需求修改 // 路由前置钩子,根据实际需求修改
router.beforeEach(async (to, from, next) => { router.beforeEach(async (to, from, next) => {
NProgress.start() NProgress.start()
// const isLogin = await store.dispatch('user-token/isLogin') // 或者user-token/isLogin
const isLogin = await store.dispatch('user/isLogin') // 或者user-token/isLogin const hasToken = getToken()
if (hasToken) {
if (isLogin) {
if (to.path === '/login') { if (to.path === '/login') {
next({path: '/'}) next({path: '/'})
NProgress.done() NProgress.done()
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论