RSA前台加密后台解密

前台代码
这里注意引入的js为jsencrypt.min.js

<!DOCTYPE html>
<html>

<head>
    <script>if (window !== top) top.location.replace(location.href);</script>
    <title>登录 - 行协数据转换应用</title>
    <meta charset="utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="${ctxPath}/assets/common/layui/css/layui.css"/>
    <link rel="stylesheet" href="${ctxPath}/assets/common/css/login.css" media="all">
    <style>
        body {
            background-image: url("${ctxPath}/assets/common/images/bg_login2.svg");
            background-position: center 110px;
            background-repeat: no-repeat;
            background-size: 100%;
            background-color: #f0f2f5;
        }

        .login-header {
            color: rgba(0, 0, 0, .85) !important;
        }

        .login-footer {
            color: rgba(0, 0, 0, 0.7) !important;
        }

        .login-footer a {
            color: rgba(0, 0, 0, 0.7) !important;
        }

        .login-footer a:hover {
            color: rgba(0, 0, 0, 0.4) !important;
        }
        .login-captcha {
            height: 38px;
            cursor: pointer;
            box-sizing: border-box;
            border: 1px solid #e6e6e6;
            border-radius: 2px !important;
        }
    </style>
    <script>
        if (window != top)
            top.location.replace(location.href);
    </script>
</head>

<body>
<div class="login-wrapper">

    <div class="login-header">
        <img src="${ctxPath}/assets/expand/images/logo.png">&nbsp;行协数据转换应用
    </div>

    <div class=" login-body">
        <div class="layui-card">
            <div class="layui-card-header">
                <i class="layui-icon layui-icon-engine"></i>&nbsp;&nbsp;用户登录
            </div>
            <form id="formId" class="layui-card-body layui-form layui-form-pane" action="${ctxPath}/login" method="post">
                <div class="layui-form-item">
                    <label class="layui-form-label">账号</label>
                    <div class="layui-input-block">
                        <input name="username"  id="username"  placeholder="请输入账号" type="text" lay-verify="required"
                               class="layui-input" value="admin">
                    </div>
                </div>
                <div class="layui-form-item">
                    <label class="layui-form-label">密码</label>
                    <div class="layui-input-block">
                        <input name="password" id="password" placeholder="请输入密码"  type="password" lay-verify="required"
                               class="layui-input" value="111111">
                    </div>
                </div>
               <!-- <div class="layui-form-item" pane="">
                    <label class="layui-form-label" lay-tips="7天内免登陆">记住我</label>
                    <div class="layui-input-block">
                        <input type="radio" name="remember" value="on" title="是">
                        <input type="radio" name="remember" value="off" title="否" checked="">
                    </div>
                </div>-->
               <!-- <div class="layui-form-item">
                    <label class="layui-form-label">验证码</label>
                    <div class="layui-input-block">
                        <div class="layui-row inline-block">
                            <div class="layui-col-xs7" style="width: 60%">
                                <input name="kaptcha" id="kaptcha" type="text" lay-verify="required" placeholder="请输入验证码" class="layui-input" style="width: 100%;">
                            </div>
                            <div class="layui-col-xs5"style="width: 40%">
                                <img class="login-captcha" src="${ctxPath}/kaptcha" style="width: 100%;padding-left: 0px">
                            </div>
                        </div>
                    </div>
                </div>-->
                <div class="layui-form-item">
                    <button lay-filter="login-submit" id="submit" class="layui-btn layui-btn-fluid Self-btn" lay-submit>登 录</button>
                </div>
            </form>
        </div>
    </div>
</div>

@/* 加入contextPath属性和session超时的配置 */
<script type="text/javascript">
    var Feng = {
        ctxPath: "",
        addCtx: function (ctx) {
            if (this.ctxPath === "") {
                this.ctxPath = ctx;
            }
        }
    };
    Feng.addCtx("${ctxPath}");
</script>
<script type="text/javascript" src="${ctxPath}/assets/common/layui/layui.js"></script>
<script type="text/javascript" src="${ctxPath}/assets/common/js/common.js"></script>
<script type="text/javascript" src="${ctxPath}/assets/modular/frame/md5.js"></script>
<script type="text/javascript" src="${ctxPath}/assets/modular/frame/jsencrypt.min.js"></script>
<script>
    layui.use(['layer', 'form'], function () {
        var $ = layui.jquery;
        var layer = layui.layer;
        var form = layui.form;


        // 表单提交
        // form.on('submit(login-submit)', function (obj) {
         $("#submit").click(function () {

        // })
            var falg = true;
            $.ajax({
                url: "/checkLogin",
                type: 'POST',
                dataType: 'json',
                data: $('#formId').serialize(),
                async:false,
                success: function(msg){
                    var publicKey=msg.data.publicKey;
                    var ip=msg.data.ip;
                    var privateKey=msg.data.privateKey;
                    console.log(privateKey)
                    var encrypt = new JSEncrypt();
                    encrypt.setPublicKey(publicKey);
                    var encrypted = encrypt.encrypt($("#password").val());

                    $("#password").val(encrypted)

                    if(ip != ''){
                        if(window.confirm("用户'"+$('#username').val()+"'已在"+msg+"登陆,是否强制登陆?")){
                            falg=true;
                        }else{
                            falg=false;
                        }
                    }
                    $('#formId').submit();
                }
            })
            return falg;
        });

        // 图形验证码
        $('.login-captcha').click(function () {
            this.src = this.src + '?t=' + (new Date).getTime();
        });

        var errorMsg = "${tips!}";
        if (errorMsg) {
            layer.msg(errorMsg, {icon: 5, anim: 6});
        }

    });
</script>
<style>
    .Self-btn {
        height: 38px;
        line-height: 38px;
        font-size: 14px;
        border-radius: 2px;
    }
</style>

</body>
</html>

后台代码CheckLogInController

package com.sinosoft.cmiip.sys.modular.system.controller;

import cn.stylefeng.roses.core.reqres.response.ResponseData;
import com.alibaba.fastjson.JSONArray;
import com.sinosoft.cmiip.sys.modular.system.util.RSAUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * 登陆前校验
 *
 * @author guobin
 * @date 2021-01-27
 */
@Controller
public class CheckLogInController {
    private final static Logger logger = LoggerFactory.getLogger(CheckLogInController.class);


    @RequestMapping(value = "/checkLogin", method = RequestMethod.POST)
    @ResponseBody
    public ResponseData CheckLogin(HttpServletRequest request, HttpServletResponse httpServletResponse) {
//        Boolean flag = false;//true-已经登陆 false-未登陆或登陆session一样
        String ip = "";//返回空-未登录。非空-已登录
        Map<String,String> map=new HashMap<>();
        Map<String, Object> mmap = new HashMap<>();
        try {
            map = RSAUtils.createRSAKeys();
            String aPublic = map.get("public");//获取公钥
            
            //获取私钥,并存入到session中
            request.getServletContext().setAttribute("privateKey",map.get("private"));
            mmap.put("publicKey",aPublic);
            
            String sessionId = request.getSession().getId();//当前sessionid
            String username = request.getParameter("username").trim();//用户名
            String sessionIdOld = (String) request.getServletContext().getAttribute(username);//老sessionId
            //如果老sessionId不为null 且新老sessionId不一致,则当前账号已有人登陆
            mmap.put("ip",ip);
            if (null != sessionIdOld && !"".equals(sessionId) && !sessionId.equals(sessionIdOld)) {
                ip = (String) request.getServletContext().getAttribute(username + "IP");
                mmap.put("ip",ip);
            }
        } catch (Exception e) {
            logger.error("从session中获取用户登陆ip失败:", e);
            ip = "";
        }

        return ResponseData.success(mmap);
    }
}

后台代码LoginController,这里只显示‘解密’方法

//获取前台传输的加密后的密码
 String password = super.getPara("password").trim();
//获取session中的私钥
  String privateKey1 =request.getServletContext().getAttribute("privateKey").toString();
 
 //解密 
password=RSAUtils.decode(password,privateKey1);

调用的解密工具类

package com.sinosoft.cmiip.sys.modular.system.util;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.crypto.Cipher;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tomcat.util.codec.binary.Base64;

public class RSAUtils {
    protected static final Log log = LogFactory.getLog(RSAUtils.class);
    private static String KEY_RSA_TYPE = "RSA";
    private static int KEY_SIZE = 1024;//JDK方式RSA加密最大只有1024位
    private static int ENCODE_PART_SIZE = KEY_SIZE/8;
    public static final String PUBLIC_KEY_NAME = "public";
    public static final String PRIVATE_KEY_NAME = "private";

    /**
     * 创建公钥秘钥
     * @return
     */
    public static Map<String,String> createRSAKeys(){
        Map<String,String> keyPairMap = new HashMap<>();//里面存放公私秘钥的Base64位加密
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_RSA_TYPE);
            keyPairGenerator.initialize(KEY_SIZE,new SecureRandom());
            KeyPair keyPair = keyPairGenerator.generateKeyPair();

            //获取公钥秘钥
            String publicKeyValue = Base64.encodeBase64String(keyPair.getPublic().getEncoded());
            String privateKeyValue = Base64.encodeBase64String(keyPair.getPrivate().getEncoded());

            //存入公钥秘钥,以便以后获取
            keyPairMap.put(PUBLIC_KEY_NAME,publicKeyValue);
            keyPairMap.put(PRIVATE_KEY_NAME,privateKeyValue);
        } catch (NoSuchAlgorithmException e) {
            log.error("当前JDK版本没找到RSA加密算法!");
            e.printStackTrace();
        }
        return keyPairMap;
    }

    /**
     * 公钥加密
     * 描述:
     *     1字节 = 8位;
     *     最大加密长度如 1024位私钥时,最大加密长度为 128-11 = 117字节,不管多长数据,加密出来都是 128 字节长度。
     * @param sourceStr
     * @param publicKeyBase64Str
     * @return
     */
    public static String encode(String sourceStr,String publicKeyBase64Str){
        byte [] publicBytes = Base64.decodeBase64(publicKeyBase64Str);
        //公钥加密
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicBytes);
        List<byte[]> alreadyEncodeListData = new LinkedList<>();

        int maxEncodeSize = ENCODE_PART_SIZE - 11;
        String encodeBase64Result = null;
        try {
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_RSA_TYPE);
            PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
            Cipher cipher = Cipher.getInstance(KEY_RSA_TYPE);
            cipher.init(Cipher.ENCRYPT_MODE,publicKey);
            byte[] sourceBytes = sourceStr.getBytes("utf-8");
            int sourceLen = sourceBytes.length;
            for(int i=0;i<sourceLen;i+=maxEncodeSize){
                int curPosition = sourceLen - i;
                int tempLen = curPosition;
                if(curPosition > maxEncodeSize){
                    tempLen = maxEncodeSize;
                }
                byte[] tempBytes = new byte[tempLen];//待加密分段数据
                System.arraycopy(sourceBytes,i,tempBytes,0,tempLen);
                byte[] tempAlreadyEncodeData = cipher.doFinal(tempBytes);
                alreadyEncodeListData.add(tempAlreadyEncodeData);
            }
            int partLen = alreadyEncodeListData.size();//加密次数

            int allEncodeLen = partLen * ENCODE_PART_SIZE;
            byte[] encodeData = new byte[allEncodeLen];//存放所有RSA分段加密数据
            for (int i = 0; i < partLen; i++) {
                byte[] tempByteList = alreadyEncodeListData.get(i);
                System.arraycopy(tempByteList,0,encodeData,i*ENCODE_PART_SIZE,ENCODE_PART_SIZE);
            }
            encodeBase64Result = Base64.encodeBase64String(encodeData);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return encodeBase64Result;
    }

    /**
     * 私钥解密
     * @param sourceBase64RSA
     * @param privateKeyBase64Str
     */
    public static String decode(String sourceBase64RSA,String privateKeyBase64Str){
        byte[] privateBytes = Base64.decodeBase64(privateKeyBase64Str);
        byte[] encodeSource = Base64.decodeBase64(sourceBase64RSA);
        int encodePartLen = encodeSource.length/ENCODE_PART_SIZE;
        List<byte[]> decodeListData = new LinkedList<>();//所有解密数据
        String decodeStrResult = null;
        //私钥解密
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateBytes);
        try {
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_RSA_TYPE);
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            Cipher cipher = Cipher.getInstance(KEY_RSA_TYPE);
            cipher.init(Cipher.DECRYPT_MODE,privateKey);
            int allDecodeByteLen = 0;//初始化所有被解密数据长度
            for (int i = 0; i < encodePartLen; i++) {
                byte[] tempEncodedData = new byte[ENCODE_PART_SIZE];
                System.arraycopy(encodeSource,i*ENCODE_PART_SIZE,tempEncodedData,0,ENCODE_PART_SIZE);
                byte[] decodePartData = cipher.doFinal(tempEncodedData);
                decodeListData.add(decodePartData);
                allDecodeByteLen += decodePartData.length;
            }
            byte [] decodeResultBytes = new byte[allDecodeByteLen];
            for (int i = 0,curPosition = 0; i < encodePartLen; i++) {
                byte[] tempSorceBytes = decodeListData.get(i);
                int tempSourceBytesLen = tempSorceBytes.length;
                System.arraycopy(tempSorceBytes,0,decodeResultBytes,curPosition,tempSourceBytesLen);
                curPosition += tempSourceBytesLen;
            }
            decodeStrResult = new String(decodeResultBytes,"UTF-8");
        }catch (Exception e){
            e.printStackTrace();
        }
        return decodeStrResult;
    }
}

效果如图
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值