网络安全面试题
一.1 安全问题
安全要素与STRIDE威胁
防范常见的Web攻击
服务端通信安全攻防
HTTPS原理剖析
HTTPS降级攻击
授权与认证
基于角色的访问控制
基于数据的访问控制
一.1.1 表单重复提交解决方案(防止Http重复提交。)
产生原因
网络延时、重新刷新、点击浏览器的【后退】按钮回退到表单页面后进行再次提交
使用javascript解决
既然存在上述所说的表单重复提交问题,那么我们就要想办法解决,比较常用的方法是采用JavaScript来防止表单重复提交,具体做法如下:
修改form.jsp页面,添加如下的JavaScript代码来防止表单重复提交
代码:
<%@pagelanguage="java"contentType="text/html;charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML4.01Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Form表单</title>
<scripttype="text/javascript">
varisFlag=false;//表单是否已经提交标识,默认为false
functionsubmitFlag(){
if(isFlag==false){
isFlag=true;
returntrue;
}else{
returnfalse;
}
}
</script>
</head>
<body>
<formaction="${pageContext.request.contextPath}/DoFormServlet"
method="post"onsubmit="returnsubmitFlag()">
用户名:<inputtype="text"name="userName"><inputtype="submit"
value="提交"id="submit">
</form>
</body>
</html>
除了用这种方式之外,经常见的另一种方式就是表单提交之后,将提交按钮设置为不可用,让用户没有机会点击第二次提交按钮,代码如下:
functiondosubmit(){
//获取表单提交按钮
varbtnSubmit=document.getElementById("submit");
//将表单提交按钮设置为不可用,这样就可以避免用户再次点击提交按钮
btnSubmit.disabled="disabled";
//返回true让表单可以正常提交
returntrue;
}
一.1.1.1 使用后端提交解决
对于【场景二】和【场景三】导致表单重复提交的问题,既然客户端无法解决,那么就在服务器端解决,在服务器端解决就需要用到session了。
具体的做法:在服务器端生成一个唯一的随机标识号,专业术语称为Token(令牌),同时在当前用户的Session域中保存这个Token。然后将Token发送到客户端的Form表单中,在Form表单中使用隐藏域来存储这个Token,表单提交的时候连同这个Token一起提交到服务器端,然后在服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,如果不一致,那就是重复提交了,此时服务器端就可以不处理重复提交的表单。如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。
在下列情况下,服务器程序将拒绝处理用户提交的表单请求:
存储Session域中的Token(令牌)与表单提交的Token(令牌)不同。
当前用户的Session中不存在Token(令牌)。
用户提交的表单数据中没有Token(令牌)。
转发代码:
@WebServlet("/ForwardServlet")
publicclassForwardServletextendsHttpServlet{
@Override
protectedvoiddoGet(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{
req.getSession().setAttribute("sesionToken",TokenUtils.getToken());
req.getRequestDispatcher("form.jsp").forward(req,resp);
}
}
转发页面:
<%@pagelanguage="java"contentType="text/html;charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML4.01Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Form表单</title>
</head>
<body>
<formaction="${pageContext.request.contextPath}/DoFormServlet"
method="post"onsubmit="returndosubmit()">
<inputtype="hidden"name="token"value="${sesionToken}">用户名:<inputtype="text"
name="userName"><inputtype="submit"value="提交"id="submit">
</form>
</body>
</html>
后端Java代码:
@WebServlet("/DoFormServlet")
publicclassDoFormServletextendsHttpServlet{
@Override
protectedvoiddoPost(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{
req.setCharacterEncoding("UTF-8");
booleanflag=isFlag(req);
if(!flag){
resp.getWriter().write("已经提交...");
System.out.println("数据已经提交了..");
return;
}
StringuserName=req.getParameter("userName");
try{
Thread.sleep(300);
}catch(Exceptione){
//TODO:handleexception
}
System.out.println("往数据库插入数据...."+userName);
resp.getWriter().write("success");
}
publicbooleanisFlag(HttpServletRequestrequest){
HttpSessionsession=request.getSession();
StringsesionToken=(String)session.getAttribute("sesionToken");
Stringtoken=request.getParameter("token");
if(!(token.equals(sesionToken))){
returnfalse;
}
session.removeAttribute("sesionToken");
returntrue;
}
}
一.1.2 如何防御XSS攻击
XSS攻击使用Javascript脚本注入进行攻击
解决办法:就是将请求可能会发送的特殊字符、javascript标签转换为html代码执行
例如在表单中注入:<script>location.href='http://www.itmayiedu.com'</script>
注意:谷歌浏览器已经防止了XSS攻击,为了演示效果,最好使用火狐浏览器
实例:
演示:
代码:fromToXss.jsp
<%@pagelanguage="java"contentType="text/html;charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML4.01Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<metahttp-equiv="Content-Type"content="text/html;charset=UTF-8">
<title>Inserttitlehere</title>
</head>
<body>
<formaction="XssDemo"method="post">
<inputtype="text"name="userName"><inputtype="submit">
</form>
</body>
</html>
代码:XssDemo
importjava.io.IOException;
importjavax.servlet.ServletException;
importjavax.servlet.annotation.WebServlet;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
@WebServlet("/XssDemo")
publicclassXssDemoextendsHttpServlet{
@Override
protectedvoiddoPost(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{
StringuserName=req.getParameter("userName");
req.setAttribute("userName",userName);
req.getRequestDispatcher("showUserName.jsp").forward(req,resp);
}
}
代码:showUserName.jsp
<%@pagelanguage="java"contentType="text/html;charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML4.01Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<metahttp-equiv="Content-Type"content="text/html;charset=UTF-8">
<title>Inserttitlehere</title>
</head>
<body>userName:${userName}
</body>
</html>
7.1解決方案
使用Fileter过滤器过滤器注入标签
FilterDemo
importjava.io.IOException;
importjava.util.Map;
importjavax.servlet.Filter;
importjavax.servlet.FilterChain;
importjavax.servlet.FilterConfig;
importjavax.servlet.ServletException;
importjavax.servlet.ServletRequest;
importjavax.servlet.ServletResponse;
importjavax.servlet.annotation.WebFilter;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
/**
*使用Filter打印参数
*
*@authorAdministrator
*
*/
publicclassFilterDemoimplementsFilter{
publicFilterDemo(){
System.out.println("FilterDemo构造函数被执行...");
}
/**
*销毁
*/
publicvoiddestroy(){
System.out.println("destroy");
}
publicvoiddoFilter(ServletRequestparamServletRequest,ServletResponseparamServletResponse,
FilterChainparamFilterChain)throwsIOException,ServletException{
System.out.println("doFilter");
HttpServletRequestrequest=(HttpServletRequest)paramServletRequest;
XssAndSqlHttpServletRequestWrapperxssRequestWrapper=newXssAndSqlHttpServletRequestWrapper(request);
paramFilterChain.doFilter(xssRequestWrapper,paramServletResponse);
}
/**
*初始化
*/
publicvoidinit(FilterConfigparamFilterConfig)throwsServletException{
System.out.println("init");
}
}
XssAndSqlHttpServletRequestWrapper
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletRequestWrapper;
importorg.apache.commons.lang3.StringEscapeUtils;
importorg.apache.commons.lang3.StringUtils;
/**
*防止XSS攻击
*/
publicclassXssAndSqlHttpServletRequestWrapperextendsHttpServletRequestWrapper{
HttpServletRequestrequest;
publicXssAndSqlHttpServletRequestWrapper(HttpServletRequestrequest){
super(request);
this.request=request;
}
@Override
publicStringgetParameter(Stringname){
Stringvalue=request.getParameter(name);
System.out.println("name:"+name+","+value);
if(!StringUtils.isEmpty(value)){
//转换Html
value=StringEscapeUtils.escapeHtml4(value);
}
returnvalue;
}
}
一.1.3 跨域实战解决方案
跨域原因产生:在当前域名请求网站中,默认不允许通过ajax请求发送其他域名。
XMLHttpRequestcannotload跨域问题解决办法
一.1.3.1 使用后台response添加header
后台response添加header,response.setHeader("Access-Control-Allow-Origin","*");支持所有网站
一.1.3.2 使用JSONP
JSONP的优缺点:
JSONP只支持get请求不支持psot请求
什么是SQL语句注入
一.1.3.3 使用接口网关
使用nginx转发。
配置:
server{
listen80;
server_namewww.itmayiedu.com;
location/A{
proxy_passhttp://a.a.com:81/A;
indexindex.htmlindex.htm;
}
location/B{
proxy_passhttp://b.b.com:81/B;
indexindex.htmlindex.htm;
}
}
相关图:
大型互联网公司网关接口系统搭建
Com/a ->代理服务器 a.a.com/a
Com/b ->代理服务器 -> b.b.com/b
一.1.1.1 使用内部服务器转发
内部服务器使用HttpClient技术进行转发
一.1.1 什么是SQL语句注入
Sql语句如果是通过拼接方式执行的话,传入参数‘or1=1会发生语句成立,导致数据错误。
应该使用PreparedStatement先编译在执行通过?号穿参数的方式进行执行。
一.1.2 怎么防御DDOC?
一.1.2.1 nginx配置DDOS
一.1.2.1.1 限制请求速度
设置Nginx、NginxPlus的连接请求在一个真实用户请求的合理范围内。比如,如果你觉得一个正常用户每两秒可以请求一次登录页面,你就可以设置Nginx每两秒钟接收一个客户端IP的请求(大约等同于每分钟30个请求)。
limit_req_zone$binary_remote_addrzone=one:10mrate=30r/m;
server{
...
location/login.html{
limit_reqzone=one;
...
}
}
`limit_req_zone`命令设置了一个叫one的共享内存区来存储请求状态的特定键值,在上面的例子中是客户端IP($binary_remote_addr)。location块中的`limit_req`通过引用one共享内存区来实现限制访问/login.html的目的。
一.1.2.1.2 限制请求速度
设置Nginx、NginxPlus的连接数在一个真实用户请求的合理范围内。比如,你可以设置每个客户端IP连接/store不可以超过10个。
评论