一、网安学习成长路线图
网安所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
二、网安视频合集
观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
三、精品网安学习书籍
当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。
四、网络安全源码合集+工具包
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
五、网络安全面试题
最后就是大家最关心的网络安全面试题板块
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
package com.caiex.vb.interceptor;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import com.caiex.vb.model.Response;
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
private Logger logger = LoggerFactory.getLogger(this.getClass());
/**
-
所有异常报错
-
@param request
-
@param exception
-
@return
-
@throws Exception
*/
@ExceptionHandler(value=Exception.class)
public Response allExceptionHandler(HttpServletRequest request,
Exception exception) throws Exception
{
logger.error(“拦截到异常:”, exception);
Response response = new Response();
response.setData(null);
response.getResult().setResultCode(9999);
response.getResult().setResultMsg(“系统繁忙”);
return response;
}
}
6.拦截器链设置:合作方访问接口的时候,会根据你接口定义好的传参访问你的接口服务器,但是会存在接口参数类型错误或者格式不对,必传参数没传的问题,甚至一些恶意请求,都可以通过拦截器链进行前期拦截,避免造成接口服务的压力。
学习资料:Java进阶视频资源
还有很重要的一点,加签验签也可以在拦截器设置。继承WebMvcConfigurerAdapter实现springboot的拦截器链。实现HandlerInterceptor方法编写业务拦截器。
package com.caiex.vb.interceptor;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSON;
import com.caiex.redis.service.api.RedisApi;
import com.caiex.vb.model.Response;
import com.caiex.vb.utils.CaiexCheckUtils;
@Component
public class SignInterceptor extends BaseValidator implements HandlerInterceptor{
private Logger logger = LogManager.getLogger(this.getClass());
@Resource
private RedisApi redisApi;
public void afterCompletion(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
// TODO Auto-generated method stub
}
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2, ModelAndView arg3) throws Exception {
// TODO Auto-generated method stub
}
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2) throws Exception {
if(isTestIpAddr(arg0)){
return true;
}
String securityKey = redisApi.hGet(“securityKey”, arg0.getParameter(“agentid”));
if(StringUtils.isEmpty(securityKey)){
Response response = new Response();
response.setData(null);
response.getResult().setResultCode(8001);
response.getResult().setResultMsg(“缺少私钥, 渠道号:” + arg0.getParameter(“agentid”));
logger.error(“缺少私钥, 渠道号:” + arg0.getParameter(“agentid”));
InterceptorResp.printJson(arg1, response);
return false;
}
if(StringUtils.isEmpty(arg0.getParameter(“sign”)) || !arg0.getParameter(“sign”).equals(CaiexCheckUtils.getSign(arg0.getParameterMap(), securityKey))){
Response response = new Response();
response.setData(null);
response.getResult().setResultCode(3203);
response.getResult().setResultMsg(“参数签名认证失败”);
logger.error(“参数签名认证失败:” + JSON.toJSONString(arg0.getParameterMap()) + " securityKey = " + securityKey);
InterceptorResp.printJson(arg1, response);
return false;
}else{
return true;
}
}
}
package com.caiex.oltp.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.caiex.oltp.interceptor.APILimitRateValidator;
import com.caiex.oltp.interceptor.CommonValidator;
import com.caiex.oltp.interceptor.DDSAuthValidator;
import com.caiex.oltp.interceptor.QueryPriceParamsValidator;
import com.caiex.oltp.interceptor.TradeParamsValidator;
@EnableWebMvc
@Configuration
@ComponentScan
public class WebAppConfigurer extends WebMvcConfigurerAdapter {
@Bean
CommonValidator commonInterceptor() {
return new CommonValidator();
}
@Bean
DDSAuthValidator ddsAuthInterceptor() {
return new DDSAuthValidator();
}
@Bean
QueryPriceParamsValidator queryPriceParamsInterceptor() {
return new QueryPriceParamsValidator();
}
@Bean
TradeParamsValidator tradeParamsInterceptor() {
return new TradeParamsValidator();
}
@Bean
APILimitRateValidator aPILimitRateInterceptor() {
return new APILimitRateValidator();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
//访问速率限制
registry.addInterceptor(aPILimitRateInterceptor())
.addPathPatterns(“//”);
//.addPathPatterns(“/price/getPriceParam”);
//参数签名认证
registry.addInterceptor(ddsAuthInterceptor())
.addPathPatterns(“/tradeState/*”)
.addPathPatterns(“/recycle/*”)
.addPathPatterns(“/matchInfo/*”)
.addPathPatterns(“/price/tradeTicketParam”);
//公共参数检查
registry.addInterceptor(commonInterceptor())
.addPathPatterns(“/price/tradeTicketParam”)
.addPathPatterns(“/tradeState/*”)
.addPathPatterns(“/recycle/*”);
//询价参数校验
registry.addInterceptor(queryPriceParamsInterceptor())
.addPathPatterns(“/price/getPriceParam”);
//交易参数检查
registry.addInterceptor(tradeParamsInterceptor())
.addPathPatterns(“/price/tradeTicketParam”);
super.addInterceptors(registry);
}
}
7.token令牌和sign数字签名实现数据保密性。
创建令牌(Token)
===========
为保证请求的合法性,我们提供第三方创建令牌接口,某些接口需要通过token验证消息的合法性,以免遭受非法攻击。
token过期时间目前暂时定为1天,由于考虑到合作方往往是分布式环境,多台机器都有可能申请token,为了降低合作方保证token一致性的难度,调用接口创建token成功以后一分钟以内,再次请求token返回的数据是一样的。
获取私钥
====
获取用于数字签名的私钥,第三方获取的私钥需妥善保存,并定期更新,私钥只参与数字签名,不作为参数传输。
数字签名方式:
参数签名;签名方式:所有值不为null的参数(不包括本参数)均参与数字签名,按照“参数名+参数值+私钥”的格式得到一个字符串,再将这个字符串MD5一次就是这个参数的值。(示例:h15adc39y9ba59abbe56e057e60f883g),所以需要先获取私钥。
验签方式:
将用户的所有非null参数放入定义好排序规则的TreeSet中进行排序,再用StringBuilder按照按照“参数名+参数值+私钥”的格式得到一个字符串(私钥从redis拿),再将这个字符串MD5一次就是这个参数的值。将这个值与用户传来的sign签名对比,相同则通过,否则不通过。
private String createToken(){
String utk = “Msk!D*”+System.currentTimeMillis()+“UBR&FLP”;
logger.info("create token — "+Md5Util.md5(utk));
return Md5Util.md5(utk);
}
8.接口限流
有时候服务器压力真的太大,以防交易接口被挤死,就可以对一些其他不影响主要业务功能并且计算量大的接口做限流处理。RateLimit–使用guava来做接口限流,当接口超过指定的流量时,就不处理该接口的请求。详细可看RateLimit。也可参考其他限流框架。
9.协议加密,http升级成https;
为什么要升级呢,为了保证数据的安全性。当使用https访问时,数据从客户端到服务断,服务端到客户端都加密,即使黑客抓包也看不到传输内容。当然还有其他好处,这里不多讲。但这也是开发接口项目需要注意的一个问题。
如何提高接口的高并发和高可用
==============
接口开发好了,接下来就讨论接口的可用性问题。首先我们要将高并发和高可用区分一下,毕竟高可用是在可用的情况,只是很慢或者效率不高。其实也可以归为一类问题,但是不重要啦,重要的是怎么提高你写的接口的访问速度和性能。
接口的高并发解决方案(其实没有唯一答案,业界针对不同业务也有很多不同的方法)
======================================
当访问一个接口获取数据时,发现返回很慢,或者总是超时,如果排除网络的原因,那就是接口服务器压力太大,处理不过来了。在世界杯期间,我们查看后台日志总是connection by reset和borker pipe和一些超时问题。
这时候,你可能遇到了高并发和高可用问题。但是,不管遇到什么问题,都不能臆断和乱改,你得需要找到慢的原因,才能对症下药,乱改可能会导致其他问题的出现。首先,解决高并发问题的三个方向是负载均衡,缓存和集群。
学习资料:Java进阶视频资源
负载均衡
====
我们使用的是阿里云服务器的负载均衡,后台分布式服务管理,我们运维小哥哥搭建了一套k8s,可以自由在k8s上扩展服务节点,各个服务结点也能随内存的使用自动漂移,不用多说,k8s真的很厉害,感兴趣的同学可以详细去学。那么问题来了,阿里云的负载均衡怎么对应到k8s的负载均衡呢?
写在最后
在结束之际,我想重申的是,学习并非如攀登险峻高峰,而是如滴水穿石般的持久累积。尤其当我们步入工作岗位之后,持之以恒的学习变得愈发不易,如同在茫茫大海中独自划舟,稍有松懈便可能被巨浪吞噬。然而,对于我们程序员而言,学习是生存之本,是我们在激烈市场竞争中立于不败之地的关键。一旦停止学习,我们便如同逆水行舟,不进则退,终将被时代的洪流所淘汰。因此,不断汲取新知识,不仅是对自己的提升,更是对自己的一份珍贵投资。让我们不断磨砺自己,与时代共同进步,书写属于我们的辉煌篇章。
需要完整版PDF学习资源私我
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!