whyczh
2022-03-07 4742357d5c0171fc33591431c8283a3b0dc01ccb
登录接口更新-添加验证码和解密
4个文件已修改
2个文件已添加
339 ■■■■■ 已修改文件
pom.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/controller/LoginController.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/controller/MessageController.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/service/LoginService.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/util/RSAUtil.java 220 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/config/application.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -160,6 +160,12 @@
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <!--commons.lang3  RSA签名验证md5使用-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.4</version>
        </dependency>
        <!--外部引入-->
        <dependency>
            <groupId>com.whyc</groupId>
src/main/java/com/whyc/controller/LoginController.java
@@ -36,6 +36,11 @@
    public Response login(@RequestParam String userName, String password,HttpServletRequest request){
        return service.login(userName,password,request);
    }
    @PostMapping("loginByRSA")
    @ApiOperation(value ="登录-账号密码加密")
    public Response loginByRSA(@RequestParam String userName, String password,String deliveredCode,HttpServletRequest request){
        return service.loginByRSA(userName,password,deliveredCode,request);
    }
    @PostMapping("loginWithUKey")
    @ApiOperation(value ="登录-uKey-TODO")
src/main/java/com/whyc/controller/MessageController.java
New file
@@ -0,0 +1,29 @@
package com.whyc.controller;
import com.whyc.dto.Response;
import com.whyc.util.ActionUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("message")
@RestController
@Api(tags = "验证码")
public class MessageController {
    @ApiOperation("获取验证码")
    @GetMapping("/getFontDynamicCode")
    public Response getFontDynamicCode(){
        StringBuilder sb = new StringBuilder();
        String originStr = "0123456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ0123456789";
        for (int i = 0; i < 4; i++) {
            sb.append(originStr.charAt((int) Math.round(Math.random()*originStr.length())));
        }
        //内存Session中存储动态口令
        ActionUtil.getSession().setAttribute("fontDynamicCode", sb.toString());
        return new Response().set(1,sb.toString());
    }
}
src/main/java/com/whyc/service/LoginService.java
@@ -4,6 +4,7 @@
import com.whyc.pojo.UserClient;
import com.whyc.pojo.UserInf;
import com.whyc.util.ActionUtil;
import com.whyc.util.RSAUtil;
import com.whyc.util.ShiroUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
@@ -12,6 +13,9 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Locale;
import java.util.Map;
@Service
@@ -39,6 +43,79 @@
        }
        return new Response<>().set(1,false,"密码错误");
    }
    public Response login2(String userName, String pwd, HttpServletRequest request) {
        String password = "";
        try {
            password = URLDecoder.decode(pwd, "utf-8");
        }catch (UnsupportedEncodingException e){
            e.printStackTrace();
        }
        String[] dataArr = RSAUtil.decryptFront(password, RSAUtil.fontSeparator);
        //验签md5
        if(!dataArr[1].equals(ActionUtil.EncryptionMD5(org.apache.commons.lang3.StringUtils.trim(dataArr[0])).toString())){
            return new Response<>().set(0,"密码验签失败");
        }
        UsernamePasswordToken userToken = new UsernamePasswordToken(userName, password);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(userToken);
        }catch (Exception e){
            String message = e.getMessage();
            if(message.contains("did not match the expected credentials")){
                return new Response<>().set(1,false,"密码错误");
            }
            return new Response<>().set(1,false,message);
        }
        if (subject.isAuthenticated()){
            //每个登录的用户都有一个全局变量,里面存着对应的SessionId;
            //同一个账号,后面登录的,会挤掉之前登录的SessionId,这个todo,做限制账号同时登陆人数为1
            request.getServletContext().setAttribute(userName,request.getSession().getId());
            //Session存储当前用户
            request.getSession().setAttribute("user",subject.getPrincipal());
            return new Response<>().setII(1,true,subject.getPrincipal(),"登录成功");
        }
        return new Response<>().set(1,false,"密码错误");
    }
    public Response loginByRSA(String userName, String pwd,String deliveredCode, HttpServletRequest request) {
        deliveredCode = deliveredCode.toUpperCase();
        String fontDynamicCode = (String) ActionUtil.getSession().getAttribute("fontDynamicCode");
        if (!deliveredCode.equals(fontDynamicCode.toUpperCase())){
            return new Response().set(1,false,"验证码错误");
        }
        //验证正确,清除验证码
        ActionUtil.getSession().removeAttribute("fontDynamicCode");
        String password = "";
        try {
            password = URLDecoder.decode(pwd, "utf-8");
        }catch (UnsupportedEncodingException e){
            e.printStackTrace();
        }
        String[] dataArr = RSAUtil.decryptFront(password, RSAUtil.fontSeparator);
        //验签md5
        if(!dataArr[1].equals(ActionUtil.EncryptionMD5(org.apache.commons.lang3.StringUtils.trim(dataArr[0])).toString())){
            return new Response<>().set(0,"密码验签失败");
        }
        UsernamePasswordToken userToken = new UsernamePasswordToken(userName, password);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(userToken);
        }catch (Exception e){
            String message = e.getMessage();
            if(message.contains("did not match the expected credentials")){
                return new Response<>().set(1,false,"密码错误");
            }
            return new Response<>().set(1,false,message);
        }
        if (subject.isAuthenticated()){
            //每个登录的用户都有一个全局变量,里面存着对应的SessionId;
            //同一个账号,后面登录的,会挤掉之前登录的SessionId,这个todo,做限制账号同时登陆人数为1
            request.getServletContext().setAttribute(userName,request.getSession().getId());
            //Session存储当前用户
            request.getSession().setAttribute("user",subject.getPrincipal());
            return new Response<>().setII(1,true,subject.getPrincipal(),"登录成功");
        }
        return new Response<>().set(1,false,"密码错误");
    }
    public Response loginWithUKey(String userName, String password, HttpServletRequest request) {
        UsernamePasswordToken userToken = new UsernamePasswordToken(userName, password);
src/main/java/com/whyc/util/RSAUtil.java
New file
@@ -0,0 +1,220 @@
package com.whyc.util;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.LinkedList;
import java.util.List;
public class RSAUtil {
    /**
     * 固定公私钥
     */
    private static final  String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCPpJ3j+SHQ69lqq+ShV7deA40Y+8rYra6rr4ReOJ+UE7ek8tsJJrcy1xMO1SophJdHXXwSNbZWhnJW9GlIq1Um6IplkwFc/AtyoeJDP3EJtUZgI5H6fSz0BPLFHn18C0Nxz1Br109U07DqQdMsarcBmKXYQw+2oZOz0KpA5b0FawIDAQAB";
    private static final  String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAI+kneP5IdDr2Wqr5KFXt14DjRj7ytitrquvhF44n5QTt6Ty2wkmtzLXEw7VKimEl0ddfBI1tlaGclb0aUirVSboimWTAVz8C3Kh4kM/cQm1RmAjkfp9LPQE8sUefXwLQ3HPUGvXT1TTsOpB0yxqtwGYpdhDD7ahk7PQqkDlvQVrAgMBAAECgYA8ASdX4W2n6a4kKnRSleLqqg8aHazqAPvTinmAJqU65VW02SJ42yxyV3gFnTSErXfIfxviO3/U+0ruWiFVEwV5oDEh0dOd+HHGm4YzFXIRglMeRBgLuVJ+owzoVDwZstiIBa69DIjaJtmpSf5FjwxAth+gtCv3e11IXHraKN720QJBAMPMB1WtmpRGYHxWVYjKSL+RGw+h3gMQLk3exZjhmYRlXuqfVZ2Zol+NazDc59K5f+geMdJ0/X2kKnKLVjWzYHMCQQC7z1cFYswtLemxGfj+dwlVC01VL4pKa7HGHl/FAQ2UNYZY2d5hE/nXYbTpfI0gMowX926/aFpia7NbAUJO7WEpAkAyUFa+LJthaOhYazMVsK2bFKW4kabkcJ8Fga6TR73UaNxIPGOa2SUBmuylpM6ptuNoeYHiDBAr3ijOQIIJ0KuDAkBy9fPahCNe9F+73J4hhVPdDtIDdto7u7hSAX215XMeabUW5iXNXqDsSg6nbWolb0t50CemWoYZALwE1Lx1+7AhAkEAoZtFt+2skjAxHEqNUye4vKBqB2Ng/wmfitCfT34lXWQsxs4BGk/8eQMzkam9bcB7FcinolxHF/1UjsUYpI+AgA==";
    /**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;
    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 128;
    public static final String fontSeparator = "&&&&&&&&&&";
    /**
     * 获取密钥对
     *
     * @return 密钥对
     */
    public static List<String> getKeyPair() throws Exception {
        LinkedList<String> list = new LinkedList<>();
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
        generator.initialize(1024);
        KeyPair keyPair = generator.generateKeyPair();
        String publicKey = Base64.encodeBase64String(keyPair.getPublic().getEncoded());
        String privateKey = Base64.encodeBase64String(keyPair.getPrivate().getEncoded());
        System.out.println("公钥:"+publicKey);
        System.out.println("私钥:"+privateKey);
        list.add(publicKey);
        list.add(privateKey);
        return list;
    }
    /**
     * 获取私钥
     *
     * @param privateKey 私钥字符串
     * @return
     */
    public static PrivateKey getPrivateKey(String privateKey) {
        try {
            KeyFactory keyFactory = null;
            keyFactory = KeyFactory.getInstance("RSA");
            byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
            return keyFactory.generatePrivate(keySpec);
        }catch (NoSuchAlgorithmException | InvalidKeySpecException e){
            return null;
        }
    }
    /**
     * 获取私钥
     *
     * @return
     */
    public static PrivateKey getPrivateKey() {
        try {
            KeyFactory keyFactory = null;
            keyFactory = KeyFactory.getInstance("RSA");
            byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
            return keyFactory.generatePrivate(keySpec);
        }catch (NoSuchAlgorithmException | InvalidKeySpecException e){
            return null;
        }
    }
    /**
     * 获取公钥
     *
     * @param publicKey 公钥字符串
     * @return
     */
    public static PublicKey getPublicKey(String publicKey) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
        return keyFactory.generatePublic(keySpec);
    }
    /**
     * 获取公钥
     *
     * @return
     */
    public static PublicKey getPublicKey(){
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
            return keyFactory.generatePublic(keySpec);
        }catch (Exception e){
            return null;
        }
    }
    /**
     * RSA加密
     *
     * @param data 待加密数据
     * @param publicKey 公钥
     * @return
     */
    public static String encrypt(String data, PublicKey publicKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            int inputLen = data.getBytes().length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offset = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段加密
            while (inputLen - offset > 0) {
                if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);
                }
                out.write(cache, 0, cache.length);
                i++;
                offset = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptedData = out.toByteArray();
            out.close();
            // 获取加密内容使用base64进行编码,并以UTF-8为标准转化成字符串
            // 加密后的字符串
            return new String(Base64.encodeBase64String(encryptedData));
        }catch (Exception e){
            return null;
        }
    }
    /**
     * RSA解密
     *
     * @param data 待解密数据
     * @param privateKey 私钥
     * @return
     */
    public static String decrypt(String data, PrivateKey privateKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] dataBytes = Base64.decodeBase64(data);
            int inputLen = dataBytes.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offset = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段解密
            while (inputLen - offset > 0) {
                if (inputLen - offset > MAX_DECRYPT_BLOCK) {
                    cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
                }
                out.write(cache, 0, cache.length);
                i++;
                offset = i * MAX_DECRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            out.close();
            // 解密后的内容
            return new String(decryptedData, "UTF-8");
        }catch (Exception e){
            return null;
        }
    }
    /**
     * 前端加密数据RSA[明文+MD5(明文)]解密为明文和MD5[明文]
     * @param frontEncryptData
     * @return
     */
    public static String[] decryptFront(String frontEncryptData,String separatorStr){
        String[] dataArr = new String[2];
        String dataMD5Mix = RSAUtil.decrypt(frontEncryptData, RSAUtil.getPrivateKey());
        int index = dataMD5Mix.indexOf(separatorStr);
        String data = dataMD5Mix.substring(0, index);
        String dataMD5 = dataMD5Mix.substring(index+separatorStr.length());
        dataArr[0] = data;
        dataArr[1] = dataMD5;
        return dataArr;
    }
    public static void main(String[] args) {
        try {
            String word = "123456";
            String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCPpJ3j+SHQ69lqq+ShV7deA40Y+8rYra6rr4ReOJ+UE7ek8tsJJrcy1xMO1SophJdHXXwSNbZWhnJW9GlIq1Um6IplkwFc/AtyoeJDP3EJtUZgI5H6fSz0BPLFHn18C0Nxz1Br109U07DqQdMsarcBmKXYQw+2oZOz0KpA5b0FawIDAQAB";
            String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAI+kneP5IdDr2Wqr5KFXt14DjRj7ytitrquvhF44n5QTt6Ty2wkmtzLXEw7VKimEl0ddfBI1tlaGclb0aUirVSboimWTAVz8C3Kh4kM/cQm1RmAjkfp9LPQE8sUefXwLQ3HPUGvXT1TTsOpB0yxqtwGYpdhDD7ahk7PQqkDlvQVrAgMBAAECgYA8ASdX4W2n6a4kKnRSleLqqg8aHazqAPvTinmAJqU65VW02SJ42yxyV3gFnTSErXfIfxviO3/U+0ruWiFVEwV5oDEh0dOd+HHGm4YzFXIRglMeRBgLuVJ+owzoVDwZstiIBa69DIjaJtmpSf5FjwxAth+gtCv3e11IXHraKN720QJBAMPMB1WtmpRGYHxWVYjKSL+RGw+h3gMQLk3exZjhmYRlXuqfVZ2Zol+NazDc59K5f+geMdJ0/X2kKnKLVjWzYHMCQQC7z1cFYswtLemxGfj+dwlVC01VL4pKa7HGHl/FAQ2UNYZY2d5hE/nXYbTpfI0gMowX926/aFpia7NbAUJO7WEpAkAyUFa+LJthaOhYazMVsK2bFKW4kabkcJ8Fga6TR73UaNxIPGOa2SUBmuylpM6ptuNoeYHiDBAr3ijOQIIJ0KuDAkBy9fPahCNe9F+73J4hhVPdDtIDdto7u7hSAX215XMeabUW5iXNXqDsSg6nbWolb0t50CemWoYZALwE1Lx1+7AhAkEAoZtFt+2skjAxHEqNUye4vKBqB2Ng/wmfitCfT34lXWQsxs4BGk/8eQMzkam9bcB7FcinolxHF/1UjsUYpI+AgA==";
            //List<String> keyPair = getKeyPair();
            //String encryptWord = encrypt(word, getPublicKey(keyPair.get(0)));
            //System.out.println("加密后的字符串:"+encryptWord);
            String encryptWord = "T8JGNiTKjeGxsy1klDEP6sgEbRIVrbC6KJt06RTY+KuK27SFU+Ch6fCE4wDsJRjfm0mr5DiHb1DZUOtEG6g4gv8F+5S7hTRtoaQkSxCCmnY7NMQKmkMl71Yvr9grx1KOrFUZCCymfcJGv0Dat7DPF/cDebnPN6IHpx+CS9u5pXI=";
            String originWord = decrypt(encryptWord, getPrivateKey(privateKey));
            System.out.println("解密后的字符串:"+originWord);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
src/main/resources/config/application.yml
@@ -80,6 +80,6 @@
  alarm:
    task.switch: off
  #Config文件读取 涉及License和FGCDFileDownload
#Config文件读取 涉及License和FGCDFileDownload
configFile:
  type: 1 #1:本地测试;2:打包jar