<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Java軟件報表軟件技術博客

    java報表軟件技術匯總 java報表軟件制作 報表軟件新聞
    posts - 355, comments - 100, trackbacks - 0, articles - 3
       :: 首頁 :: 新隨筆 ::  :: 聚合  :: 管理

    RSA加密算法是目前最有影響力的公鑰加密算法,它能夠抵抗到目前為止已知的絕大多數密碼攻擊。

    那關于RSA加密算法有哪些應用呢?以下舉一個數據庫身份驗證的案例。

    在使用數據集進行身份認證時,密碼存在數據庫中,認證時用戶輸入的密碼與數據庫中密碼相同則認證通過,若數據庫被破解了則對系統造成威脅,怎樣保證系統安全呢?這里就可以應用RSA加密算法,對權限加密。

    思路:

    就是在url中傳用戶名密碼時,先把用戶名進行翻轉,然后再進行加密,如輸入的密碼為12,實際后臺進行加密的值為21,再與數據庫進行驗證,這樣就可以避免數據庫被破解查看到的是21的加密碼,登陸系統時以21是無法登陸成功的。

    以報表軟件FineReport為例,這是一個能讀取各類數據庫的報表軟件,分客戶端和前端展示。

    實現方案:

    1、把RSA加密使用的第三方包,放到工程web-inf/lib文件夾下即可。

    2、調用js文件

    RSA文件夾為前端js加密時需要調用js文件,因此需要將Barrett.js、BigInt.js、RSA.js放到工程目錄下如:WebReport/js,新建js文件夾放入js文件。

    3、定義RSA加密類

    定義RSAUtil.java類文件,先運行類中generateKeyPair()方法,會在服務器D盤中生成一個隨機的RSAKey.txt文件,保存公鑰和密鑰,每訪問一次這個方法會刷新一

    次txt文件。

    package com.fr.privilege;

    import java.io.ByteArrayOutputStream;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.math.BigInteger;
    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.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    import java.security.spec.InvalidKeySpecException;
    import java.security.spec.RSAPrivateKeySpec;
    import java.security.spec.RSAPublicKeySpec;

    import javax.crypto.Cipher;

    /**
     * RSA 工具類。提供加密,解密,生成密鑰對等方法。
     * 需要到http://www.bouncycastle.org下載bcprov-jdk14-123.jar。
     * 
     
    */

    public class RSAUtil {
        
    /**
         * * 生成密鑰對 *
         * 
         * 
    @return KeyPair *
         * 
    @throws EncryptException
         
    */

        
    public static KeyPair generateKeyPair() throws Exception {
            
    try {
                KeyPairGenerator keyPairGen 
    = KeyPairGenerator.getInstance("RSA",
                        
    new org.bouncycastle.jce.provider.BouncyCastleProvider());
                
    final int KEY_SIZE = 1024;// 沒什么好說的了,這個值關系到塊加密的大小,可以更改,但是不要太大,否則效率會低
                keyPairGen.initialize(KEY_SIZE, new SecureRandom());
                KeyPair keyPair 
    = keyPairGen.generateKeyPair();
                saveKeyPair(keyPair);
                
    return keyPair;
            }
     catch (Exception e) {
                
    throw new Exception(e.getMessage());
            }

        }


        
    public static KeyPair getKeyPair() throws Exception {
            FileInputStream fis 
    = new FileInputStream("C:/RSAKey.txt");
            ObjectInputStream oos 
    = new ObjectInputStream(fis);
            KeyPair kp 
    = (KeyPair) oos.readObject();
            oos.close();
            fis.close();
            
    return kp;
        }


        
    public static void saveKeyPair(KeyPair kp) throws Exception {

            FileOutputStream fos 
    = new FileOutputStream("C:/RSAKey.txt");
            ObjectOutputStream oos 
    = new ObjectOutputStream(fos);
            
    // 生成密鑰
            oos.writeObject(kp);
            oos.close();
            fos.close();
        }


        
    /**
         * * 生成公鑰 *
         * 
         * 
    @param modulus *
         * 
    @param publicExponent *
         * 
    @return RSAPublicKey *
         * 
    @throws Exception
         
    */

        
    public static RSAPublicKey generateRSAPublicKey(byte[] modulus,
                
    byte[] publicExponent) throws Exception {
            KeyFactory keyFac 
    = null;
            
    try {
                keyFac 
    = KeyFactory.getInstance("RSA",
                        
    new org.bouncycastle.jce.provider.BouncyCastleProvider());
            }
     catch (NoSuchAlgorithmException ex) {
                
    throw new Exception(ex.getMessage());
            }


            RSAPublicKeySpec pubKeySpec 
    = new RSAPublicKeySpec(new BigInteger(
                    modulus), 
    new BigInteger(publicExponent));
            
    try {
                
    return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);
            }
     catch (InvalidKeySpecException ex) {
                
    throw new Exception(ex.getMessage());
            }

        }


        
    /**
         * * 生成私鑰 *
         * 
         * 
    @param modulus *
         * 
    @param privateExponent *
         * 
    @return RSAPrivateKey *
         * 
    @throws Exception
         
    */

        
    public static RSAPrivateKey generateRSAPrivateKey(byte[] modulus,
                
    byte[] privateExponent) throws Exception {
            KeyFactory keyFac 
    = null;
            
    try {
                keyFac 
    = KeyFactory.getInstance("RSA",
                        
    new org.bouncycastle.jce.provider.BouncyCastleProvider());
            }
     catch (NoSuchAlgorithmException ex) {
                
    throw new Exception(ex.getMessage());
            }


            RSAPrivateKeySpec priKeySpec 
    = new RSAPrivateKeySpec(new BigInteger(
                    modulus), 
    new BigInteger(privateExponent));
            
    try {
                
    return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);
            }
     catch (InvalidKeySpecException ex) {
                
    throw new Exception(ex.getMessage());
            }

        }


        
    /**
         * * 加密 *
         * 
         * 
    @param key
         *            加密的密鑰 *
         * 
    @param data
         *            待加密的明文數據 *
         * 
    @return 加密后的數據 *
         * 
    @throws Exception
         
    */

        
    public static byte[] encrypt(PublicKey pk, byte[] data) throws Exception {
            
    try {
                Cipher cipher 
    = Cipher.getInstance("RSA",
                        
    new org.bouncycastle.jce.provider.BouncyCastleProvider());
                cipher.init(Cipher.ENCRYPT_MODE, pk);
                
    int blockSize = cipher.getBlockSize();// 獲得加密塊大小,如:加密前數據為128個byte,而key_size=1024
                
    // 加密塊大小為127
                
    // byte,加密后為128個byte;因此共有2個加密塊,第一個127
                
    // byte第二個為1個byte
                int outputSize = cipher.getOutputSize(data.length);// 獲得加密塊加密后塊大小
                int leavedSize = data.length % blockSize;
                
    int blocksSize = leavedSize != 0 ? data.length / blockSize + 1
                        : data.length 
    / blockSize;
                
    byte[] raw = new byte[outputSize * blocksSize];
                
    int i = 0;
                
    while (data.length - i * blockSize > 0{
                    
    if (data.length - i * blockSize > blockSize)
                        cipher.doFinal(data, i 
    * blockSize, blockSize, raw, i
                                
    * outputSize);
                    
    else
                        cipher.doFinal(data, i 
    * blockSize, data.length - i
                                
    * blockSize, raw, i * outputSize);
                    
    // 這里面doUpdate方法不可用,查看源代碼后發現每次doUpdate后并沒有什么實際動作除了把byte[]放到
                    
    // ByteArrayOutputStream中,而最后doFinal的時候才將所有的byte[]進行加密,可是到了此時加密塊大小很可能已經超出了
                    
    // OutputSize所以只好用dofinal方法。

                    i
    ++;
                }

                
    return raw;
            }
     catch (Exception e) {
                
    throw new Exception(e.getMessage());
            }

        }


        
    /**
         * * 解密 *
         * 
         * 
    @param key
         *            解密的密鑰 *
         * 
    @param raw
         *            已經加密的數據 *
         * 
    @return 解密后的明文 *
         * 
    @throws Exception
         
    */

        
    public static byte[] decrypt(PrivateKey pk, byte[] raw) throws Exception {
            
    try {
                Cipher cipher 
    = Cipher.getInstance("RSA",
                        
    new org.bouncycastle.jce.provider.BouncyCastleProvider());
                cipher.init(cipher.DECRYPT_MODE, pk);
                
    int blockSize = cipher.getBlockSize();
                ByteArrayOutputStream bout 
    = new ByteArrayOutputStream(64);
                
    int j = 0;

                
    while (raw.length - j * blockSize > 0{
                    bout.write(cipher.doFinal(raw, j 
    * blockSize, blockSize));
                    j
    ++;
                }

                
    return bout.toByteArray();
            }
     catch (Exception e) {
                
    throw new Exception(e.getMessage());
            }

        }


        
    /**
         * * *
         * 
         * 
    @param args *
         * 
    @throws Exception
         
    */

        
    public static void main(String[] args) throws Exception {
            RSAPublicKey rsap 
    = (RSAPublicKey) RSAUtil.generateKeyPair()
                    .getPublic();
            String test 
    = "hello world";
            
    byte[] en_test = encrypt(getKeyPair().getPublic(), test.getBytes());
            System.out.println(
    "123:" + new String(en_test));
            
    byte[] de_test = decrypt(getKeyPair().getPrivate(), en_test);
            System.out.println(
    new String(de_test));
        }

    }

    4、定義密碼驗證類

    定義TestPasswordValidatorRSA.java密碼驗證類

    定義一個類,命名為TestPasswordValidatorRSA.java,擴展于AbstractPasswordValidator,重寫其中密碼驗證方法encodePassword,先把輸入的密碼進行翻轉,然后再進行加密,返回密碼進行驗證,具體代碼如下:

    package com.fr.privilege;  

    import com.fr.privilege.providers.dao.AbstractPasswordValidator;  
    public class TestPasswordValidatorRSA extends AbstractPasswordValidator{  
        
    //@Override
        public String encodePassword( String clinetPassword) {
            
    try {
                
    //對密碼進行翻轉如輸入ab翻轉后為ba
                StringBuffer sb = new StringBuffer();  
                sb.append(
    new String(clinetPassword));
                String bb 
    = sb.reverse().toString();
                
    //進行加密
                byte[] en_test = RSAUtil.encrypt(RSAUtil.getKeyPair().getPublic(),bb.getBytes());             
                
    //進行解密,如果數據庫里面保存的是加密碼,則此處不需要進行解密
                byte[] de_test = RSAUtil.decrypt(RSAUtil.getKeyPair().getPrivate(),en_test);  
                
    //返回加密密碼
                clinetPassword=new String(de_test);        
            }
     catch (Exception e) {
                
    // TODO Auto-generated catch block
                e.printStackTrace();
            }

            
    return clinetPassword; //即獲取加密密碼再與數據庫密碼匹配。  
        }


        @Override
        
    public boolean validatePassword(String arg0, String arg1) {
            
    // TODO Auto-generated method stub
            return false;
        }



    }

    5、編譯類文件

    首先編譯RSAUtil.java類文件在服務器的D盤生成RSAKey.txt文件,再編譯TestPasswordValidatorRSA.java類,把編譯后的class文件放到項目工程web-inf/classes/com/fr/privilege文件夾中。

    6、登陸Login.jsp頁面設置

    客戶端請求到登錄頁面,隨機生成一字符串,此隨機字符串作為密鑰加密密碼,如下代碼:

    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <%@page import="com.fr.privilege.providers.dao.RSAUtil"%>
    <%!public String Testmo() {
            String module 
    = "";
            
    try {
                java.security.interfaces.RSAPublicKey rsap 
    = (java.security.interfaces.RSAPublicKey) RSAUtil
                        .getKeyPair().getPublic();
                module 
    = rsap.getModulus().toString(16);
            }
     catch (Exception e) {
                
    // TODO Auto-generated catch block
                e.printStackTrace();
            }

            
    return module;
        }
    %>
    <%!public String Testem() {
            String empoent 
    = "";
            
    try {
                java.security.interfaces.RSAPublicKey rsap 
    = (java.security.interfaces.RSAPublicKey) RSAUtil
                        .getKeyPair().getPublic();
                empoent 
    = rsap.getPublicExponent().toString(16);
            }
     catch (Exception e) {
                
    // TODO Auto-generated catch block
                e.printStackTrace();
            }

            
    return empoent;
        }
    %>
    <html>
        
    <head>
            
    <script type="text/javascript"
                src
    ="ReportServer?op=emb&resource=finereport.js"></script>
            
    <script type="text/javascript" src="js/RSA.js"></script>
            
    <script type="text/javascript" src="js/BigInt.js"></script>
            
    <script type="text/javascript" src="js/Barrett.js"></script>
            
    <script type="text/javascript">    
        
    function bodyRSA()  
        
    {  
        setMaxDigits(
    130);  
        
    var a = "<%=Testmo()%>";
        
    var b = "<%=Testem()%>";
        key 
    = new RSAKeyPair(b,"",a);
        }
     
    function doSubmit() {   
        bodyRSA(); 
        
    var username = FR.cjkEncode(document.getElementById("username").value); //獲取輸入的用戶名    
        var password = FR.cjkEncode(document.getElementById("password").value);  //獲取輸入的參數    
        $.ajax({    
            url : 
    "ReportServer?op=auth_login&fr_username=" + username + "&fr_password=" + password,   //將用戶名和密碼發送到報表認證地址op=auth_login   
            data : {__redirect__ : 'false'},        
            complete : 
    function(res) {    
                
    var jo = FR.jsonDecode(res.responseText);    
                
    if(jo.url) {    
                   window.location
    =jo.url+ "&_=" + new Date().getTime();   //認證成功跳轉頁面,因為ajax不支持重定向所有需要跳轉的設置  
                }
        
                
    else{    
                   alert(
    "用戶名密碼錯誤!")  //認證失敗    
                }
        
            }
        
        }
    )    
    }
        
    </script>
        
    </head>
        
    <body>
            
    <p>
                請登錄
            
    </p>
            
    <form name="login" method="POST">
                
    <p>
                    用戶名:
                    
    <input id="username" type="text" />
                
    </p>
                
    <p>
                    密 碼:
                    
    <input id="password" type="password" />
                
    </p>
                
    <input type="button" value="登錄" onclick="doSubmit()"  />
            
    </form>
        
    </body>
    </html>



    主站蜘蛛池模板: 久久久高清日本道免费观看| 亚洲欧美成aⅴ人在线观看| 国产亚洲精品第一综合| 国产精品久久免费| 亚洲视频在线不卡| 黄页免费在线观看| 亚洲av无码成h人动漫无遮挡 | 成人免费视频网址| 亚洲精品无码久久久久久久| baoyu777永久免费视频| 国产亚洲精品无码拍拍拍色欲| 在线观看国产一区亚洲bd| 免费无码又爽又刺激聊天APP| 99久久精品国产亚洲| 久久中文字幕免费视频| 亚洲资源在线视频| 在线观看AV片永久免费| 男人的天堂av亚洲一区2区| 四虎永久免费地址在线网站| 免费国产va视频永久在线观看| 亚洲福利精品一区二区三区| 国产精品玖玖美女张开腿让男人桶爽免费看 | 亚洲高清在线视频| 边摸边脱吃奶边高潮视频免费 | 亚洲AV无码久久久久网站蜜桃| 欧洲乱码伦视频免费| youjizz亚洲| 亚洲Aⅴ无码一区二区二三区软件| 污污污视频在线免费观看| 亚洲国产另类久久久精品小说| 久久久精品免费视频| 亚洲粉嫩美白在线| 国产成人精品日本亚洲专区61| 久9这里精品免费视频| 亚洲人精品亚洲人成在线| 亚洲国产电影av在线网址| 久久九九AV免费精品| 国产精品亚洲五月天高清| 久久精品亚洲一区二区| 成熟女人特级毛片www免费| 国产成人AV免费观看|