Java 登录安全漏洞防护

1、某地区公共数据平台系统测试漏洞结果

漏洞名称漏洞等级
暴力破解(验证码可绕)
CORS 资源共享跨域漏洞
存在 .DS_Store 文件泄露

2、漏洞定级依据

序号
漏洞等级
描述
1
紧急
可以直接被利用的漏洞,且利用难度较低。被攻击之后可能对网站
或服务器的正常运行造成严重影响,或对用户财产及个人信息造成
重大损失。
2
高危
被利用之后,造成的影响较大,但直接利用难度较高的漏洞。或本
身无法直接攻击,但能为进一步攻击造成极大便利的漏洞。
3
中危
利用难度极高,或满足严格条件才能实现攻击的漏洞。或漏洞本身
无法被直接攻击,但能为进一步攻击起较大帮助作用的漏洞。
4
低危
无法直接实现攻击,但提供的信息可能让攻击者更容易找到其他安
全漏洞。

3、【中危】暴力破解(验证码可绕)

(1)漏洞描述

       由于没有对登录页面进行相关的人机验证机制,如无验证码、有验证码但可重复利用以
及无登录错误次数限制等

(2)漏洞危害

      该漏洞导致攻击者可通过暴力破解可能获取用户登录账号和密码。

(3)测试截图:

      验证码可绕过进行暴力破解,验证码并不在同一登录数据包校验

 

(4)解决方案:

1、将验证码验证业务从客户端 AJAX 改为服务端验证

原验证码验证方式:

            // 验证验证码是否正确
            var validateCode = $("#validateCode").val();
            if(!validateCode){
                $("#messageBox").removeClass("none");
                $("#messageBox").text("验证码不可为空");
                return;
            }

            //验证码客户端验证
            submitData("${pageContext.request.contextPath}/servlet/validateCodeServlet",{validateCode:validateCode},function(data){
                if(data) {
                    login();
                } else {
                    $("#messageBox").removeClass("none");
                    $("#messageBox").text("验证码错误, 请重试.");
                    $('.validateCodeRefresh').click();
                }
            }, {}, 'get', false);
  • 服务端生成二维码和唯一标识存入 Redis;
 /**
     * 验证码生成
     * @param request
     * @param response
     * @throws IOException
     */
    private void createImage(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0L);
        response.setContentType("image/jpeg");
        String width = request.getParameter("width");
        String height = request.getParameter("height");
        if (StringUtils.isNumeric(width) && StringUtils.isNumeric(height)) {
            this.w = NumberUtils.toInt(width);
            this.h = NumberUtils.toInt(height);
        }

        BufferedImage image = new BufferedImage(this.w, this.h, 1);
        Graphics g = image.getGraphics();
        this.createBackground(g);
        Code character = this.createCharacter(g);
        request.getSession().setAttribute(VALIDATE_CODE, character.getS());
        g.dispose();
        OutputStream out = response.getOutputStream();
        ImageIO.write(image, "JPEG", out);
        out.close();
        //生成验证码唯一标识
        String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 20);
//        //唯一标识传入Session
        request.getSession().setAttribute(VALIDATE_UUID,uuid);
        //唯一标识和验证码存入缓存
        LoginNumTimes.storeVerificationCode(VALIDATE_UUID+uuid,character.getCode());

    }

    private Color getRandColor(int fc, int bc) {
        int f = fc;
        int b = bc;
        Random random = new Random();
        if (fc > 255) {
            f = 255;
        }

        if (bc > 255) {
            b = 255;
        }

        return new Color(f + random.nextInt(b - f), f + random.nextInt(b - f), f + random.nextInt(b - f));
    }

    private void createBackground(Graphics g) {
        g.setColor(this.getRandColor(220, 250));
        g.fillRect(0, 0, this.w, this.h);

        for(int i = 0; i < 8; ++i) {
            g.setColor(this.getRandColor(40, 150));
            Random random = new Random();
            int x = random.nextInt(this.w);
            int y = random.nextInt(this.h);
            int x1 = random.nextInt(this.w);
            int y1 = random.nextInt(this.h);
            g.drawLine(x, y, x1, y1);
        }

    }

    private Code createCharacter(Graphics g) {
        char[] codeSeq = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9'};
        String[] fontTypes = new String[]{"Arial", "Arial Black", "AvantGarde Bk BT", "Calibri"};
        Random random = new Random();
        StringBuilder s = new StringBuilder();

        String c = "";
        for(int i = 0; i < 4; ++i) {
            String r = String.valueOf(codeSeq[random.nextInt(codeSeq.length)]);
            c = c+r;
            g.setColor(new Color(50 + random.nextInt(100), 50 + random.nextInt(100), 50 + random.nextInt(100)));
            g.setFont(new Font(fontTypes[random.nextInt(fontTypes.length)], 1, 26));
            g.drawString(r, 15 * i + 5, 19 + random.nextInt(8));
            s.append(r);
        }
        return new Code(s.toString(),c);
    }
  • 用户登录时再将 session 中 的唯一标识带回服务端从 Redis 中获取二维码进行比对;
        //扫码登录
        if(isCode){
            if (credential instanceof RememberMeUsernamePasswordCredential){
                //扫码登录标志
                ((RememberMeUsernamePasswordCredential) credential).setCode(true);
                //扫码授权码
                ((RememberMeUsernamePasswordCredential) credential).setCode(code);
            }
        }else {
            //服务端验证码验证
            String uuid = (String) request.getSession().getAttribute(ValidateCodeServlet.VALIDATE_UUID);
            String s = JedisUtils.get(ValidateCodeServlet.VALIDATE_UUID + uuid);
            try {
                if (s==null){
                    loginLogService.saveLog(request, username, new Exception("验证码已过期,请刷新后重新输入"), "用户登录失败:" + username);
                    Map<String, Class<? extends Exception>> handlerErrors = new HashMap<>();
                    handlerErrors.put("VerificationCodeExpiredException",VerificationCodeExpiredException.class);
                    throw new AuthenticationException(handlerErrors);
                }
            }catch (AuthenticationException e){
                logger.error("AuthenticationViaFormAction.VerificationCodeExpiredException",e);
                return newEvent(AUTHENTICATION_FAILURE, e);
            }
            try {
                if (!s.equals(validateCode)){
                loginLogService.saveLog(request, username, new Exception("验证码不正确,请重新输入"), "用户登录失败:" + username);
                    Map<String, Class<? extends Exception>> handlerErrors = new HashMap<>();
                    handlerErrors.put("VerificationCodeException",VerificationCodeException.class);
                    throw new AuthenticationException(handlerErrors);
            }
            }catch (AuthenticationException e){
                logger.error("AuthenticationViaFormAction.VerificationCodeException",e);
                return newEvent(AUTHENTICATION_FAILURE, e);
            }

            if (!StringUtils.hasText(username)) {
                context.getFlowScope().put("AUTHENTICATION_FAILURE", "required.username");
                loginLogService.saveLog(request, username, new Exception("登录用户名为空"), "用户登录失败,登录用户名为空");
                return newEvent(AUTHENTICATION_FAILURE);
            }
            if (!StringUtils.hasText(password)) {
                context.getFlowScope().put("AUTHENTICATION_FAILURE", "required.password");
                loginLogService.saveLog(request, username, new Exception("登录密码为空"), "用户登录失败:" + username);
                return newEvent(AUTHENTICATION_FAILURE);
            }
        }
  • 所有业务 整合 security 安全框架,回显提示语和 sql 语句均编写在配置文件中,未在代码中体现。
/**
 * @Author: 张佑威
 * @Date: Created in 14:24 2022/7/4
 * @Description: 身份验证异常处理程序
 * @Modified By:
 */
public class AuthenticationExceptionHandler{

        /** State name when no matching exception is found. */
        private static final String UNKNOWN = "UNKNOWN";

        /** Default message bundle prefix. */
        private static final String DEFAULT_MESSAGE_BUNDLE_PREFIX = "authenticationFailure.";

        /** Default list of errors this class knows how to handle. */
        private static final List<Class<? extends Exception>> DEFAULT_ERROR_LIST =
                new ArrayList<Class<? extends Exception>>();

        private final Logger logger = LoggerFactory.getLogger(this.getClass());

        static {
            DEFAULT_ERROR_LIST.add(javax.security.auth.login.AccountLockedException.class);
            DEFAULT_ERROR_LIST.add(javax.security.auth.login.FailedLoginException.class);
            DEFAULT_ERROR_LIST.add(javax.security.auth.login.CredentialExpiredException.class);
            DEFAULT_ERROR_LIST.add(javax.security.auth.login.AccountNotFoundException.class);
            DEFAULT_ERROR_LIST.add(org.jasig.cas.authentication.AccountDisabledException.class);
            DEFAULT_ERROR_LIST.add(org.jasig.cas.authentication.InvalidLoginLocationException.class);
            DEFAULT_ERROR_LIST.add(org.jasig.cas.authentication.InvalidLoginTimeException.class);
            DEFAULT_ERROR_LIST.add(DingUserUnboundException.class);
            DEFAULT_ERROR_LIST.add(DingUserNotExistException.class);
            DEFAULT_ERROR_LIST.add(VerificationCodeException.class);
            DEFAULT_ERROR_LIST.add(VerificationCodeExpiredException.class);
            DEFAULT_ERROR_LIST.add(TooManyAccountLoginsException.class);
            DEFAULT_ERROR_LIST.add(TooManyIPRequestsException.class);
        }

        /** Ordered list of error classes that this class knows how to handle. */
        @NotNull
        private List<Class<? extends Exception>> errors = DEFAULT_ERROR_LIST;

        /** String appended to exception class name to create a message bundle key for that particular error. */
        private String messageBundlePrefix = DEFAULT_MESSAGE_BUNDLE_PREFIX;

        /**
         * Sets the list of errors that this class knows how to handle.
         *
         * @param errors List of errors in order of descending precedence.
         */
        public void setErrors(final List<Class<? extends Exception>> errors) {
            this.errors = errors;
        }

        public final List<Class<? extends Exception>> getErrors() {
            return Collections.unmodifiableList(this.errors);
        }

        /**
         * Sets the message bundle prefix appended to exception class names to create a message bundle key for that
         * particular error.
         *
         * @param prefix Prefix appended to exception names.
         */
        public void setMessageBundlePrefix(final String prefix) {
            this.messageBundlePrefix = prefix;
        }

        /**
         * Maps an authentication exception onto a state name equal to the simple class name of the
         * {@link org.jasig.cas.authentication.AuthenticationException#getHandlerErrors()} with highest precedence.
         * Also sets an ERROR severity message in the message context of the form
         * <code>[messageBundlePrefix][exceptionClassSimpleName]</code> for each handler error that is
         * configured. If not match is found, {@value #UNKNOWN} is returned.
         *
         * @param e Authentication error to handle.
         *
         * @return Name of next flow state to transition to or {@value #UNKNOWN}
         */
        public String handle(final AuthenticationException e, final MessageContext messageContext) {
            if (e != null) {
                for (final Class<? extends Exception> kind : this.errors) {
                    for (final Class<? extends Exception> handlerError : e.getHandlerErrors().values()) {
                        if (handlerError != null && handlerError.equals(kind)) {
                            final String messageCode = this.messageBundlePrefix + handlerError.getSimpleName();
                            messageContext.addMessage(new MessageBuilder().error().code(messageCode).build());
                            return handlerError.getSimpleName();
                        }
                    }

                }
            }
            final String messageCode = this.messageBundlePrefix + UNKNOWN;
            logger.trace("Unable to translate handler errors of the authentication exception {}. Returning {} by default...", e, messageCode);
            messageContext.addMessage(new MessageBuilder().error().code(messageCode).build());
            return UNKNOWN;
        }
  • properties配置文件中添加回显信息异常统一读取
#Generic Success Screen Messages
screen.success.header=登录成功
screen.success.success=您已经成功登录中央认证系统。
screen.success.security=出于安全考虑,一旦您访问过那些需要您提供凭证信息的应用时,请操作完成之后关闭浏览器。

# Authentication failure messages
authenticationFailure.AccountDisabledException=账号不可用
authenticationFailure.AccountLockedException=账号输入错误次数过多,已被锁定
authenticationFailure.CredentialExpiredException=密码过期
#authenticationFailure.InvalidLoginLocationException=You cannot login from this workstation.
#authenticationFailure.InvalidLoginTimeException=Your account is forbidden to login at this time.
#authenticationFailure.AccountNotFoundException=该账号不存在,请先注册!
#authenticationFailure.AccountNotFoundException=该用户不存在,请先添加用户!
authenticationFailure.AccountNotFoundException=用户名或密码不正确,请重新输入!
#authenticationFailure.FailedLoginException=密码不正确,请重新输入!
authenticationFailure.FailedLoginException=用户名或密码不正确,请重新输入!
authenticationFailure.UNKNOWN=用户名和密码都不能为空!
authenticationFailure.VerificationCodeException=验证码错误,请重新输入!
authenticationFailure.VerificationCodeExpiredException=验证码过期,请刷新后重新输入!
authenticationFailure.TooManyAccountLoginsException=连续登录次数已达上限,请10分钟后再试!
authenticationFailure.TooManyIPRequestsException=当日IP请求次数已达上限,请1小时后再试!
authenticationFailure.DingUserNotExistException=未获取到浙政钉用户信息!
authenticationFailure.DingUserUnboundException=未查到相关用户信息,请联系管理员绑定浙政钉账号!
  • 编写自定义异常类,整合security异常统一处理
异常名作用场景
DingUserNotExistException
浙政厅用户找不到异常
DingUserUnboundException
浙政钉未绑定异常
TooManyAccountLoginsException
连续登录次数已达上限
TooManyIPRequestsException
当日IP请求次数已达上限
VerificationCodeException
验证码错误,请重新输入!
VerificationCodeExpiredException
验证码过期,请刷新后重新输入!
/**
 * @Author: 张佑威
 * @Date: Created in 14:24 2022/7/4
 * @Description: 连续登录次数已达上限
 * @Modified By:
 */
public class TooManyAccountLoginsException extends AccountException implements Serializable {
    private static final long serialVersionUID = 1318370463436736729L;

    /**
     * Constructs a AccountException with no detail message. A detail
     * message is a String that describes this particular exception.
     */
    public TooManyAccountLoginsException() {
    }

    /**
     * Constructs a AccountException with the specified detail message.
     * A detail message is a String that describes this particular
     * exception.
     *
     * <p>
     *
     * @param msg the detail message.
     */
    public TooManyAccountLoginsException(String msg) {
        super(msg);
    }
}

2.针对恶意破解行为,加设业务逻辑:


      同一用户 10 分钟内超 过 5 次重复登录或同一 IP 地址在 1 小时内重复登录请求 10 次则将该用户名或 IP 地址存入 Redis 中,锁定其对应时间。

        //查询登录次数,校验是否超过阔值
        Boolean loginKey = LoginNumTimes.getLoginKey(username);
        try {
        if (loginKey!=true){
            loginLogService.saveLog(request, username, new Exception("连续登录次数已达上限,请10分钟后再试。"), "用户登录失败:" + username);
            Map<String, Class<? extends Exception>> handlerErrors = new HashMap<>();
            handlerErrors.put("TooManyAccountLoginsException",TooManyAccountLoginsException.class);
            throw new AuthenticationException(handlerErrors);
        }
        }catch (AuthenticationException e){
            logger.error("AuthenticationViaFormAction.TooManyAccountLoginsException",e);
            return newEvent(AUTHENTICATION_FAILURE, e);
        }


        //获取请求IP
        String ip = IpUtils.getIP(request);
        Boolean ipKey = LoginNumTimes.getIPKey(ip);
        try {
            if (ipKey != true) {
                loginLogService.saveLog(request, username, new Exception("当日IP请求次数已达上限,请24小时后再试。"), "用户登录失败:" + username);
                Map<String, Class<? extends Exception>> handlerErrors = new HashMap<>();
                handlerErrors.put("TooManyIPRequestsException",TooManyIPRequestsException.class);
                throw new AuthenticationException(handlerErrors);
            }
        }catch (AuthenticationException e){
            logger.error("AuthenticationViaFormAction.TooManyIPRequestsException",e);
            return newEvent(AUTHENTICATION_FAILURE, e);
        }

        /**
         * 1.验证码校验通过
         * 2.账号锁定验证通过
         * 3.IP锁定验证通过
         */
        LoginNumTimes.setLoginNumTimes(username);
        LoginNumTimes.setIPTimes(ip);

/**
 * @Author: 张佑威
 * @Date: Created in 14:24 2022/6/29
 * @Description: 限制用户重复登录次数
 * @Modified By:
 */
public class LoginNumTimes {

    /**
     * 登录时间间隔(秒)
     */
    private static final int TIME_INTERVAL = 600;
    /**
     * 登录时间间隔(秒)
     */
    private static final int TIME_IP = 1800;
    /**
     * 每10分钟内登录次数上限(次)
     */
    private static final int FAILED_RETRY_TIMES = 5;
    /**
     * 同一IP当日请求次数上限(次)
     */
    private static final int IP_RETRY_TIMES = 10;
    /**
     * 验证码失效时间(秒)
     */
    private static final int VERIFICATIONCODE_RETRY_TIMES = 360;
    /**
     * redis记录用户登录次数key
     */
    private static final String USER_LOGIN_FAILED_COUNT = "USER:LOGIN:FAILED:COUNT:";
    /**
     * redis记录IP请求次数key
     */
    private static final String IP_LOGIN_FAILED_COUNT = "IP:LOGIN:FAILED:COUNT:";

    /**
     * 检验是否超出单日最大可登录次数
     * @return
     */
    public static Boolean getLoginKey(String username){
        String key = USER_LOGIN_FAILED_COUNT + username;
        String redisCounter = getRedisCounter(key);
        if (Integer.parseInt(redisCounter)>=FAILED_RETRY_TIMES){
            return false;
        }else {
            return true;
        }
    }


    /**
     * 检验是否超出单日最大可登录次数
     * @return
     */
    public static Boolean getIPKey(String ip){
        String key = IP_LOGIN_FAILED_COUNT + ip;
        String IpCounter = getRedisCounter(key);
        if (Integer.parseInt(IpCounter)>=IP_RETRY_TIMES){
            return false;
        }else {
            return true;
        }
    }



    /**
     * 根据key获取计数器
     *
     * @param key key
     * @return
     */
    private static String getRedisCounter(String key) {
        return JedisUtils.get(key)==null?"0":JedisUtils.get(key);
    }

    /**
     * 更新登录次数记录
     * @param username
     */
    public static void setLoginNumTimes(String username){
        String key = USER_LOGIN_FAILED_COUNT + username;
        String value = JedisUtils.get(key);
        if (value!=null){
            String newVlue = String.valueOf(Integer.parseInt(value)+1);
            JedisUtils.set(key,newVlue,TIME_INTERVAL);
        }else {
            JedisUtils.set(key,"1",TIME_INTERVAL);
        }

    }


    /**
     * 更新IP请求次数记录
     * @param ip
     */
    public static void setIPTimes(String ip){
        String key = IP_LOGIN_FAILED_COUNT + ip;
        String IpCounter = getRedisCounter(key);
        if (IpCounter!=null){
            String newVlue = String.valueOf(Integer.parseInt(IpCounter)+1);
            JedisUtils.set(key,newVlue,TIME_IP);
        }else {
            JedisUtils.set(key,"1",TIME_IP);
        }

    }


    /**
     * 存储验证码失效时间
     * @param key
     * @param VerificationCode
     */
    public static void storeVerificationCode(String key,String VerificationCode){
        JedisUtils.set(key,VerificationCode,VERIFICATIONCODE_RETRY_TIMES);

    }
    
}

JedisUtils
public class JedisUtils {

    public static Pool jedisPool = JedisApi.getPool();

    public static Logger log = LoggerFactory.getLogger(JedisUtils.class);

    /**
     * 获取缓存
     * @param key 键
     * @return 值
     */
    public static String get(String key) {
        String value = null;
        Jedis jedis = null;
        try {
            jedis = getResource();
            if (jedis.exists(key)) {
                value = jedis.get(key);
                value = StringUtils.isNotBlank(value) && !"nil".equalsIgnoreCase(value) ? value : null;
                log.debug("get {} = {}", key, value);
            }
        } catch (Exception e) {
            log.warn("get {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return value;
    }

    /**
     * 获取缓存
     * @param key 键
     * @return 值
     */
    public static Object getObject(String key) {
        Object value = null;
        Jedis jedis = null;
        try {
            jedis = getResource();
            if (jedis.exists(getBytesKey(key))) {
                value = toObject(jedis.get(getBytesKey(key)));
                log.debug("getObject {} = {}", key, value);
            }
        } catch (Exception e) {
            log.warn("getObject {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return value;
    }

    /**
     * 设置缓存
     * @param key 键
     * @param value 值
     * @param cacheSeconds 超时时间,0为不超时
     * @return
     */
    public static String set(String key, String value, int cacheSeconds) {
        String result = null;
        Jedis jedis = null;
        try {
            jedis = getResource();
            result = jedis.set(key, value);
            if (cacheSeconds != 0) {
                jedis.expire(key, cacheSeconds);
            }
            log.debug("set {} = {}", key, value);
        } catch (Exception e) {
            log.warn("set {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 设置缓存
     * @param key 键
     * @param value 值
     * @param cacheSeconds 超时时间,0为不超时
     * @return
     */
    public static String setObject(String key, Object value, int cacheSeconds) {
        String result = null;
        Jedis jedis = null;
        try {
            jedis = getResource();
            result = jedis.set(getBytesKey(key), toBytes(value));
            if (cacheSeconds != 0) {
                jedis.expire(key, cacheSeconds);
            }
            log.debug("setObject {} = {}", key, value);
        } catch (Exception e) {
            log.warn("setObject {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 获取List缓存
     * @param key 键
     * @return 值
     */
    public static List<String> getList(String key) {
        List<String> value = null;
        Jedis jedis = null;
        try {
            jedis = getResource();
            if (jedis.exists(key)) {
                value = jedis.lrange(key, 0, -1);
                log.debug("getList {} = {}", key, value);
            }
        } catch (Exception e) {
            log.warn("getList {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return value;
    }

    /**
     * 获取List缓存
     * @param key 键
     * @return 值
     */
    public static List<Object> getObjectList(String key) {
        List<Object> value = null;
        Jedis jedis = null;
        try {
            jedis = getResource();
            if (jedis.exists(getBytesKey(key))) {
                List<byte[]> list = jedis.lrange(getBytesKey(key), 0, -1);
                value = Lists.newArrayList();
                for (byte[] bs : list){
                    value.add(toObject(bs));
                }
                log.debug("getObjectList {} = {}", key, value);
            }
        } catch (Exception e) {
            log.warn("getObjectList {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return value;
    }

    /**
     * 设置List缓存
     * @param key 键
     * @param value 值
     * @param cacheSeconds 超时时间,0为不超时
     * @return
     */
    public static long setList(String key, List<String> value, int cacheSeconds) {
        long result = 0;
        Jedis jedis = null;
        try {
            jedis = getResource();
            if (jedis.exists(key)) {
                jedis.del(key);
            }
            result = jedis.rpush(key, (String[])value.toArray());
            if (cacheSeconds != 0) {
                jedis.expire(key, cacheSeconds);
            }
            log.debug("setList {} = {}", key, value);
        } catch (Exception e) {
            log.warn("setList {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 设置List缓存
     * @param key 键
     * @param value 值
     * @param cacheSeconds 超时时间,0为不超时
     * @return
     */
    public static long setObjectList(String key, List<Object> value, int cacheSeconds) {
        long result = 0;
        Jedis jedis = null;
        try {
            jedis = getResource();
            if (jedis.exists(getBytesKey(key))) {
                jedis.del(key);
            }
            List<byte[]> list = Lists.newArrayList();
            for (Object o : value){
                list.add(toBytes(o));
            }
            result = jedis.rpush(getBytesKey(key), (byte[][])list.toArray());
            if (cacheSeconds != 0) {
                jedis.expire(key, cacheSeconds);
            }
            log.debug("setObjectList {} = {}", key, value);
        } catch (Exception e) {
            log.warn("setObjectList {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 向List缓存中添加值
     * @param key 键
     * @param value 值
     * @return
     */
    public static long listAdd(String key, String... value) {
        long result = 0;
        Jedis jedis = null;
        try {
            jedis = getResource();
            result = jedis.rpush(key, value);
            log.debug("listAdd {} = {}", key, value);
        } catch (Exception e) {
            log.warn("listAdd {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 向List缓存中添加值
     * @param key 键
     * @param value 值
     * @return
     */
    public static long listObjectAdd(String key, Object... value) {
        long result = 0;
        Jedis jedis = null;
        try {
            jedis = getResource();
            List<byte[]> list = Lists.newArrayList();
            for (Object o : value){
                list.add(toBytes(o));
            }
            result = jedis.rpush(getBytesKey(key), (byte[][])list.toArray());
            log.debug("listObjectAdd {} = {}", key, value);
        } catch (Exception e) {
            log.warn("listObjectAdd {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 获取缓存
     * @param key 键
     * @return 值
     */
    public static Set<String> getSet(String key) {
        Set<String> value = null;
        Jedis jedis = null;
        try {
            jedis = getResource();
            if (jedis.exists(key)) {
                value = jedis.smembers(key);
                log.debug("getSet {} = {}", key, value);
            }
        } catch (Exception e) {
            log.warn("getSet {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return value;
    }

    /**
     * 获取缓存
     * @param key 键
     * @return 值
     */
    public static Set<Object> getObjectSet(String key) {
        Set<Object> value = null;
        Jedis jedis = null;
        try {
            jedis = getResource();
            if (jedis.exists(getBytesKey(key))) {
                value = Sets.newHashSet();
                Set<byte[]> set = jedis.smembers(getBytesKey(key));
                for (byte[] bs : set){
                    value.add(toObject(bs));
                }
                log.debug("getObjectSet {} = {}", key, value);
            }
        } catch (Exception e) {
            log.warn("getObjectSet {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return value;
    }

    /**
     * 设置Set缓存
     * @param key 键
     * @param value 值
     * @param cacheSeconds 超时时间,0为不超时
     * @return
     */
    public static long setSet(String key, Set<String> value, int cacheSeconds) {
        long result = 0;
        Jedis jedis = null;
        try {
            jedis = getResource();
            if (jedis.exists(key)) {
                jedis.del(key);
            }
            result = jedis.sadd(key, (String[])value.toArray());
            if (cacheSeconds != 0) {
                jedis.expire(key, cacheSeconds);
            }
            log.debug("setSet {} = {}", key, value);
        } catch (Exception e) {
            log.warn("setSet {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 设置Set缓存
     * @param key 键
     * @param value 值
     * @param cacheSeconds 超时时间,0为不超时
     * @return
     */
    public static long setObjectSet(String key, Set<Object> value, int cacheSeconds) {
        long result = 0;
        Jedis jedis = null;
        try {
            jedis = getResource();
            if (jedis.exists(getBytesKey(key))) {
                jedis.del(key);
            }
            Set<byte[]> set = Sets.newHashSet();
            for (Object o : value){
                set.add(toBytes(o));
            }
            result = jedis.sadd(getBytesKey(key), (byte[][])set.toArray());
            if (cacheSeconds != 0) {
                jedis.expire(key, cacheSeconds);
            }
            log.debug("setObjectSet {} = {}", key, value);
        } catch (Exception e) {
            log.warn("setObjectSet {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 向Set缓存中添加值
     * @param key 键
     * @param value 值
     * @return
     */
    public static long setSetAdd(String key, String... value) {
        long result = 0;
        Jedis jedis = null;
        try {
            jedis = getResource();
            result = jedis.sadd(key, value);
            log.debug("setSetAdd {} = {}", key, value);
        } catch (Exception e) {
            log.warn("setSetAdd {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 向Set缓存中添加值
     * @param key 键
     * @param value 值
     * @return
     */
    public static long setSetObjectAdd(String key, Object... value) {
        long result = 0;
        Jedis jedis = null;
        try {
            jedis = getResource();
            Set<byte[]> set = Sets.newHashSet();
            for (Object o : value){
                set.add(toBytes(o));
            }
            result = jedis.rpush(getBytesKey(key), (byte[][])set.toArray());
            log.debug("setSetObjectAdd {} = {}", key, value);
        } catch (Exception e) {
            log.warn("setSetObjectAdd {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 获取Map缓存
     * @param key 键
     * @return 值
     */
    public static Map<String, String> getMap(String key) {
        Map<String, String> value = null;
        Jedis jedis = null;
        try {
            jedis = getResource();
            if (jedis.exists(key)) {
                value = jedis.hgetAll(key);
                log.debug("getMap {} = {}", key, value);
            }
        } catch (Exception e) {
            log.warn("getMap {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return value;
    }

    /**
     * 获取Map缓存
     * @param key 键
     * @return 值
     */
    public static Map<String, Object> getObjectMap(String key) {
        Map<String, Object> value = null;
        Jedis jedis = null;
        try {
            jedis = getResource();
            if (jedis.exists(getBytesKey(key))) {
                value = Maps.newHashMap();
                Map<byte[], byte[]> map = jedis.hgetAll(getBytesKey(key));
                for (Map.Entry<byte[], byte[]> e : map.entrySet()){
                    value.put(StringUtils.toString(e.getKey()), toObject(e.getValue()));
                }
                log.debug("getObjectMap {} = {}", key, value);
            }
        } catch (Exception e) {
            log.warn("getObjectMap {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return value;
    }

    /**
     * 设置Map缓存
     * @param key 键
     * @param value 值
     * @param cacheSeconds 超时时间,0为不超时
     * @return
     */
    public static String setMap(String key, Map<String, String> value, int cacheSeconds) {
        String result = null;
        Jedis jedis = null;
        try {
            jedis = getResource();
            if (jedis.exists(key)) {
                jedis.del(key);
            }
            result = jedis.hmset(key, value);
            if (cacheSeconds != 0) {
                jedis.expire(key, cacheSeconds);
            }
            log.debug("setMap {} = {}", key, value);
        } catch (Exception e) {
            log.warn("setMap {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 设置Map缓存
     * @param key 键
     * @param value 值
     * @param cacheSeconds 超时时间,0为不超时
     * @return
     */
    public static String setObjectMap(String key, Map<String, Object> value, int cacheSeconds) {
        String result = null;
        Jedis jedis = null;
        try {
            jedis = getResource();
            if (jedis.exists(getBytesKey(key))) {
                jedis.del(key);
            }
            Map<byte[], byte[]> map = Maps.newHashMap();
            for (Map.Entry<String, Object> e : value.entrySet()){
                map.put(getBytesKey(e.getKey()), toBytes(e.getValue()));
            }
            result = jedis.hmset(getBytesKey(key), (Map<byte[], byte[]>)map);
            if (cacheSeconds != 0) {
                jedis.expire(key, cacheSeconds);
            }
            log.debug("setObjectMap {} = {}", key, value);
        } catch (Exception e) {
            log.warn("setObjectMap {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 向Map缓存中添加值
     * @param key 键
     * @param value 值
     * @return
     */
    public static String mapPut(String key, Map<String, String> value) {
        String result = null;
        Jedis jedis = null;
        try {
            jedis = getResource();
            result = jedis.hmset(key, value);
            log.debug("mapPut {} = {}", key, value);
        } catch (Exception e) {
            log.warn("mapPut {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 向Map缓存中添加值
     * @param key 键
     * @param value 值
     * @return
     */
    public static String mapObjectPut(String key, Map<String, Object> value) {
        String result = null;
        Jedis jedis = null;
        try {
            jedis = getResource();
            Map<byte[], byte[]> map = Maps.newHashMap();
            for (Map.Entry<String, Object> e : value.entrySet()){
                map.put(getBytesKey(e.getKey()), toBytes(e.getValue()));
            }
            result = jedis.hmset(getBytesKey(key), (Map<byte[], byte[]>)map);
            log.debug("mapObjectPut {} = {}", key, value);
        } catch (Exception e) {
            log.warn("mapObjectPut {} = {}", key, value, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 移除Map缓存中的值
     * @param key 键
     * @param mapKey 值
     * @return
     */
    public static long mapRemove(String key, String mapKey) {
        long result = 0;
        Jedis jedis = null;
        try {
            jedis = getResource();
            result = jedis.hdel(key, mapKey);
            log.debug("mapRemove {}  {}", key, mapKey);
        } catch (Exception e) {
            log.warn("mapRemove {}  {}", key, mapKey, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 移除Map缓存中的值
     * @param key 键
     * @param mapKey 值
     * @return
     */
    public static long mapObjectRemove(String key, String mapKey) {
        long result = 0;
        Jedis jedis = null;
        try {
            jedis = getResource();
            result = jedis.hdel(getBytesKey(key), getBytesKey(mapKey));
            log.debug("mapObjectRemove {}  {}", key, mapKey);
        } catch (Exception e) {
            log.warn("mapObjectRemove {}  {}", key, mapKey, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 判断Map缓存中的Key是否存在
     * @param key 键
     * @param mapKey 值
     * @return
     */
    public static boolean mapExists(String key, String mapKey) {
        boolean result = false;
        Jedis jedis = null;
        try {
            jedis = getResource();
            result = jedis.hexists(key, mapKey);
            log.debug("mapExists {}  {}", key, mapKey);
        } catch (Exception e) {
            log.warn("mapExists {}  {}", key, mapKey, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 判断Map缓存中的Key是否存在
     * @param key 键
     * @param mapKey 值
     * @return
     */
    public static boolean mapObjectExists(String key, String mapKey) {
        boolean result = false;
        Jedis jedis = null;
        try {
            jedis = getResource();
            result = jedis.hexists(getBytesKey(key), getBytesKey(mapKey));
            log.debug("mapObjectExists {}  {}", key, mapKey);
        } catch (Exception e) {
            log.warn("mapObjectExists {}  {}", key, mapKey, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 删除缓存
     * @param key 键
     * @return
     */
    public static long del(String key) {
        long result = 0;
        Jedis jedis = null;
        try {
            jedis = getResource();
            if (jedis.exists(key)){
                result = jedis.del(key);
                log.debug("del {}", key);
            }else{
                log.debug("del {} not exists", key);
            }
        } catch (Exception e) {
            log.warn("del {}", key, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 删除缓存
     * @param key 键
     * @return
     */
    public static long delObject(String key) {
        long result = 0;
        Jedis jedis = null;
        try {
            jedis = getResource();
            if (jedis.exists(getBytesKey(key))){
                result = jedis.del(getBytesKey(key));
                log.debug("delObject {}", key);
            }else{
                log.debug("delObject {} not exists", key);
            }
        } catch (Exception e) {
            log.warn("delObject {}", key, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 缓存是否存在
     * @param key 键
     * @return
     */
    public static boolean exists(String key) {
        boolean result = false;
        Jedis jedis = null;
        try {
            jedis = getResource();
            result = jedis.exists(key);
            log.debug("exists {}", key);
        } catch (Exception e) {
            log.warn("exists {}", key, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 缓存是否存在
     * @param key 键
     * @return
     */
    public static boolean existsObject(String key) {
        boolean result = false;
        Jedis jedis = null;
        try {
            jedis = getResource();
            result = jedis.exists(getBytesKey(key));
            log.debug("existsObject {}", key);
        } catch (Exception e) {
            log.warn("existsObject {}", key, e);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 获取资源
     * @return
     * @throws JedisException
     */
    public static Jedis getResource() throws JedisException {
        Jedis jedis = null;
        try {
            jedis = (Jedis) jedisPool.getResource();
//			log.debug("getResource.", jedis);
        } catch (JedisException e) {
            log.warn("getResource.", e);
            returnBrokenResource(jedis);
            throw e;
        }
        return jedis;
    }

    /**
     * 归还资源
     * @param jedis
     */
    public static void returnBrokenResource(Jedis jedis) {
        if (jedis != null) {
            jedisPool.returnBrokenResource(jedis);
        }
    }

    /**
     * 释放资源
     * @param jedis
     */
    public static void returnResource(Jedis jedis) {
        if (jedis != null) {
            jedisPool.returnResource(jedis);
        }
    }

    /**
     * 获取byte[]类型Key
     * @param object
     * @return
     */
    public static byte[] getBytesKey(Object object){
        if(object instanceof String){
            return StringUtils.getBytes((String)object);
        }else{
            return ObjectUtils.serialize(object);
        }
    }

    /**
     * Object转换byte[]类型
     * @param object
     * @return
     */
    public static byte[] toBytes(Object object){
        return ObjectUtils.serialize(object);
    }

    /**
     * byte[]型转换Object
     * @param bytes
     * @return
     */
    public static Object toObject(byte[] bytes){
        return ObjectUtils.unserialize(bytes);
    }
}

4、【中危】CORS 资源共享跨域漏洞

(1)漏洞描述

      跨域资源共享 (CORS) 是一种放宽同源策略的机制,它允许浏览器向跨源服务器,发出
XMLHttpRequest 请求,从而克服了 AJAX 只能同源使用的限制,以使不同的网站可以跨
域获取数据,跨域资源共享 CORS 漏洞主要是由于程序员配置不当,对于 Origin 源校验
不严格,从而造成跨域问题。

(2)漏洞危害

      攻击者可以利用 CORS 错误配置漏洞,从恶意网站跨域读取受害网站的敏感信息。

(3)测试截图

      Origin 可以任意调整

(4)加固方法

  1. 1、禁止配置 “Access-Control-Allow-Origin” 为 “
  2. *” 和 “null”;
  3. 2、严格校验 “Origin” 值,避免出现权限泄露;
  4. 3、避免使用 “Access-Control-Allow-Credentials:true”;
  5. 4、减少 “Access-Control-Allow-Methods” 所允许的方法;

5、【低危】存在.DS_Store 文件泄露

(1)漏洞描述   

      .DS_Store Mac Finder 用来保存如何展示 文件 / 文件夹 的数据文件,每个文件夹
下对应一个。

(2)漏洞危害

      由于开发/设计人员在发布代码时未删除文件夹中隐藏的.DS_store,可能造成文件目录
结构泄漏、源代码文件等敏感信息的泄露。

(3)测试截图

      通过该文件可以获取部分网站结构、文件信息

(4)解决方法

进入该项目部署Linux环境,通过查看nginx配置信息,找到项目根目录

使用模糊查找命令和删除命令删除所有.DS_Store 文件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柚几哥哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值