zoukankan      html  css  js  c++  java
  • web安全编码Demo

     目录:

    1、生成安全随机数

    2、密码安全存储

    3、文件上传

    4、SQL注入

    5、HMAC-SHA256

    一、生成安全随机数

    用于生成会话sessionid、防CSRF时的token、以及其他场景下的veritycode。

    如下代码:生成安全随机数

    package net.xdclass.demo;
    import java.security.SecureRandom;
    
    /**
     * 使用安全随机数生成器生成24byte的随机数
     */
    
    public class OtherTest {
        public static StringBuilder createToken(){
            SecureRandom random = new SecureRandom();
            byte bytes[] =  new byte[24];
            random.nextBytes(bytes);
            StringBuilder  token = new StringBuilder();
            String hv;
            for (int i=0;i<bytes.length;i++){
                int j = bytes[i] & 0xFF;
                hv = Integer.toHexString(j);
                if (hv.length()==1){
                    hv = "0"+hv;
                }
                token.append(hv);
            }
            return token;
        }
    
        public static  void  main(String[] args){
            System.out.println(createToken());
            System.out.println(createToken().length());
    
        }
    }

    二、密码安全存储

    • 禁止使用MD5、SHA1不安全哈希算法
    • 可以使用SHA256+salt,salt随机生成,salt长度不低于8byte,每个用户的salt不一样,salt存数据库
    • 强烈建议使用PBKDF2秘钥推到函数,安全存储用户密码

    如下代码:PBKDF2存储密码DEMO

    package net.xdclass.demo;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.PBEKeySpec;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    import java.security.spec.InvalidKeySpecException;
    import java.sql.Array;
    
    /**
     * 使用PBKDF2生成不可逆的密码
     * DK = PBKDF2(PRF, Password, Salt, c, dkLen)
     * * PRF是一个伪随机函数,例如HASH_HMAC函数,它会输出长度为hLen的结果。
     * * Password是用来生成密钥的原文密码。
     * * Salt是一个加密用的盐值。
     * * c是进行重复计算的次数。
     * * dkLen是期望得到的密钥的长度。
     * * DK是最后产生的密钥。
     */
    
    public class OtherTest {
        public static StringBuilder savePassword(String password)throws NoSuchAlgorithmException, InvalidKeySpecException {
            SecureRandom random = new SecureRandom();
            byte salt[] =  new byte[24];
            random.nextBytes(salt);
            int iterCount=5000;//迭代次数不低于5000次
            char[] charPassword = password.toCharArray();
            PBEKeySpec pbeKeySpec = new PBEKeySpec(charPassword,salt,iterCount,256);
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
            byte[] hashpassword = secretKeyFactory.generateSecret(pbeKeySpec).getEncoded();
            StringBuilder  finalPassword = new StringBuilder();
            String hv;
            for (int i=0;i<hashpassword.length;i++){
                int j = hashpassword[i] & 0xFF;
                hv = Integer.toHexString(j);
                if (hv.length()==1){
                    hv = "0"+hv;
                }
                finalPassword.append(hv);
                }
            return finalPassword;
        }
        public static  void  main(String[] args) throws NoSuchAlgorithmException,InvalidKeySpecException {
            System.out.println(savePassword("123456"));
        }
    }

    三、文件上传

    • 服务端通过白名单限制上传的文件类型
    • 限制文件的大小
    • 限制文件保存的目录,禁止执行权限
    • 压缩包需要考虑解压后大小、文件名是否包含目录跳转字符
    • 对上传的文件重命名,上传的路径禁止返回客户端

    如下代码:获取文件类型,并判断文件名是否包含空格DEMO

    package net.xdclass.demo;
    import java.io.File;
    
    /**
     * 获取上传文件的文件类型,并判断文件名是否包含空
     */
    
    public class OtherTest {
        public static  void  main(String[] args) {
            //取上传文件的文件名
            String path="D:\MyDocument\3-java\2-Code\demo.java";
            File file  = new File(path);
            String fileName = file.getName();
            StringBuilder finalFileName = new StringBuilder();
            //去除文件名中的空字符
            for (int i=0;i<fileName.length();i++){
                if ('u0000' != fileName.charAt(i)){
                    finalFileName.append(fileName.charAt(i));
                }
            }
            int i = finalFileName.lastIndexOf(".");
            String fileExtension = finalFileName.substring(i+1);
            System.out.println(fileExtension);
        }
    }

    四、SQL注入

    防范SQL注入的方法:

    • 预编译
    • 对不可信的数据进行处理
    • 对不可信的数据进行编码

    如下代码:通过预编译的方式防范SQL注入漏洞

    1、错误示例,拼接SQL语句,导致存在SQL注入漏洞

    package Eleven;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.Statement;
    import java.sql.*;
    
    public class OtherTest {
        public static void main(String[] args)  throws  ClassNotFoundException, SQLException  {
            Class.forName("com.mysql.cj.jdbc.Driver");
            Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/user_info?serverTimezone=UTC", "root", "123456");
            Statement stmt = null;
            ResultSet rsSet = null;
    
            String userName = "Eleven' or '1'='1'-- ";  //拼接一个用户名,形成万能查询
            String userPassword = "123456";
            String sqlString = "select * from user where name = '" + userName +"' AND password = '" + userPassword + "'"; // 变量未经处理直接与SQL语句拼接在一起
            stmt = conn.createStatement();
            rsSet = stmt.executeQuery(sqlString);
            while(rsSet.next()) {
                String name = rsSet.getString("name");
                String password = rsSet.getString("password");
                System.out.println(name+" "+password);  //输出结果为数据库所有的用户名密码。
            }
        }
    }

    2、正确示例

    package Eleven;
    import java.sql.*;
    
    public class Test {
        public static void main(String[] args) throws  ClassNotFoundException, SQLException {
            Class.forName("com.mysql.cj.jdbc.Driver");
            Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/user_info?serverTimezone=UTC", "root", "123456");
            String userName="Eleven";
            String userPwd="123456";
            String sql = " SELECT * FROM `user` WHERE name=? and password=? ";
            PreparedStatement pstate = conn.prepareStatement(sql);
            pstate.setString(1, userName);
            pstate.setString(2, userPwd);
            ResultSet rsSet = pstate.executeQuery();
    
            while(rsSet.next()) {
                String name = rsSet.getString("name");
                String password = rsSet.getString("password");
                System.out.println(name+" "+password);  
            }
            rsSet.close();
            pstate.cancel();
            conn.close();
        }
    }

    五、HMAC-SHA256

    import javax.crypto.Mac;
    import javax.crypto.spec.SecretKeySpec;
    
    public class Sha256_mac {
        public static String sha256_mac(String message,String key){
            String outPut= null;
            try{
                Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
                SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(),"HmacSHA256");
                sha256_HMAC.init(secret_key);
                byte[] bytes = sha256_HMAC.doFinal(message.getBytes());
                outPut = byteArrayToHexString(bytes);
            }catch (Exception e){
                System.out.println("Error HmacSHA256========"+e.getMessage());
            }
            return outPut;
        }
        public static String byteArrayToHexString(byte[] b) {
            StringBuilder sb = new StringBuilder();
            String stmp;
            for (int n = 0; b != null && n < b.length; n++) {
                stmp = Integer.toHexString(b[n] & 0XFF);
                if (stmp.length() == 1)
                    sb.append('0');
                sb.append(stmp);
            }
            return sb.toString().toLowerCase();
        }
    
    }

    六、

    七、

  • 相关阅读:
    particcles.js in 安卓WebView
    PDF.js 主页样式以及获取流
    Oracle授权A中的表给B
    安卓Response 获取body的正确方式
    android.util.Base64 和 org.apache.commons.codec.binary.Base64
    DAY62-前端入门-javascript(九)jQurey高级
    DAY61-前端入门-javascript(八)jQurey
    DAY60-前端入门-javascript(七)JS动画 | JS盒模型 | DOM | BOM
    DAY59-前端入门-javascript(六)JS事件
    DAY58-前端入门-javascript(五)JS常用类
  • 原文地址:https://www.cnblogs.com/Eleven-Liu/p/11148337.html
Copyright © 2011-2022 走看看