安全性是六大质量属性中及其重要的,往往被开发者忽略;但如果忽略了安全性出现安全问题却是难以挽救的。
(一)安全性战术的目标是:
1,检测网络攻击;
2,抵抗网络攻击;
3,很快的从攻击中恢复。
(二)常见的安全攻击有:
1,XSS攻击:即跨站点脚本攻击,指黑客通过篡改网页,注入恶意HTML脚本,在用户浏览网页时,控制用户浏览器进行恶意操作的一种攻击方式。分类:反射型和持久型
解决方式:1,消毒(将特殊字符转义)2,禁止访问带有HttpOnly的敏感Cookie数据,
2,注入攻击:如SQL注入,OS注入
解决方式:1,消毒(通过正则表达式过滤可能的恶意SQL命令)2,参数绑定
3,CSRF攻击:跨站点请求伪造,伪造用户请求
解决方式:1,添加表单Token(标记)2,验证码3,Referer check
4,Error Code:错误回显,通过系统报错的信息寻找漏洞
解决方式:通过配置web服务器参数跳转500专门错误页面
5,HTML注释:
6,文件上传:通过上传可执行程序进行攻击。
解决方式:限制上传文件类型
7,路径遍历
(三)提起安全性就不得不提数据加密的问题,常见的数据加密:
- 单项散列加密:将要加密的信息进行散列计算得到固定长度的输出信息。为了安全性,可以给散列算法添加密匙(salt)增加破解难度。常见的相应算法:MD5,SHA。只能将明文转为密文;不能将密文转为明文。
- 对称加密:加密和解密使用同一个密匙(或互相推算);优点:算法简单,加解密效率高,系统开销小,适合对大量数据加密;缺点:使用同一个密匙,远程通信下难以安全的交换。常用算法:DES,RC
- 非对称加密:加密和解密使用不同的密匙;公匙对外公开,私匙只有所有者知道;使用公匙加密,则使用私匙解密;使用私匙加密,则使用公匙解密。常用算法:RSA,HTTPS传输使用的数字证书就是非对称加密的公匙。
(四)安全性常用战术:
(五)安全性在信息热词系统中的使用:
1,首先用户注册登录的账号和密码要进行信息加密;避免不法用户破解密码;(3DES加密)
import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.Security; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.KeyGenerator; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; public class EncrypDES3 { // KeyGenerator 提供对称密钥生成器的功能,支持各种算法 private KeyGenerator keygen; // SecretKey 负责保存对称密钥 private SecretKey deskey; // Cipher负责完成加密或解密工作 private Cipher c; // 该字节数组负责保存加密的结果 private byte[] cipherByte; public EncrypDES3() throws NoSuchAlgorithmException, NoSuchPaddingException { // 实例化支持DES算法的密钥生成器(算法名称命名需按规定,否则抛出异常) keygen = KeyGenerator.getInstance("DESede"); // 生成密钥 deskey = keygen.generateKey(); // 生成Cipher对象,指定其支持的DES算法 c = Cipher.getInstance("DESede"); } /** * 对字符串加密 */ public byte[] Encrytor(String str) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException { // 根据密钥,对Cipher对象进行初始化,ENCRYPT_MODE表示加密模式 c.init(Cipher.ENCRYPT_MODE, deskey); byte[] src = str.getBytes(); // 加密,结果保存进cipherByte cipherByte = c.doFinal(src); return cipherByte; } /** * 对字符串解密 */ public byte[] Decryptor(byte[] buff) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException { // 根据密钥,对Cipher对象进行初始化,DECRYPT_MODE表示加密模式 c.init(Cipher.DECRYPT_MODE, deskey); cipherByte = c.doFinal(buff); return cipherByte; } /** * 主函数 */ public static void main(String[] args) throws Exception { EncrypDES3 des = new EncrypDES3(); String msg ="You are not alone."; byte[] encontent = des.Encrytor(msg); byte[] decontent = des.Decryptor(encontent); System.out.println("明文是:" + msg); System.out.println("加密后:" + new String(encontent)); System.out.println("解密后:" + new String(decontent)); } }
2,其次在用户输入账号和密码时添加输入验证码,防止暴力破解,以及需要查询词条等所有输入框禁止用户输入非法字符。从而避免SQL注入问题;
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <base href="/Mvcpro/"/> <meta charset="UTF-8"> <title>Insert title here</title> <script type="text/javascript" src="js/jquery.min.js"></script> </head> <body> <span>${msg}</span> <form action="emp/login" method="POST"> <fieldset> <legend>请登录!</legend> 用户名:<input type="text" name="username" placehodler="输入用户名"><br><br> 密 码: <input type="password" name="pwd" placehodler="输入密码"><br><br> <img alt="图片不存在" src="imgCode" height="40px"><a href="javascript:void"> 看不清,换一张!</a><br><br> 验证码:<input type="text" name="code"> <br><br> <input type="submit" value="提交"> <input type="reset" value="重置"> </fieldset> </form> <script type="text/javascript"> $(function(){ $("form a").click(function(){//为a标签绑定了一个单机事件 $("form img").attr("src","imgCode?ran="+new Date().getTime()); }) }) </script> </body> </html> package com.sxt.mvcpro.util; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Random; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @WebServlet("/imgCode") public class RandomCode extends HttpServlet { private static final long serialVersionUID = 1L; private static int WIDTH = 102;//定义验证图片的宽度 private static int HEIGHT = 50;//定义验证图片的高度 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); response.setContentType("image/jpeg"); ServletOutputStream sos = response.getOutputStream(); response.setHeader("Pragma", "No-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); Graphics g = image.getGraphics(); char[] rands = generateCheckCode(); drawBackground(g); drawRands(g, rands); g.dispose(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ImageIO.write(image, "JPEG", bos); byte[] buf = bos.toByteArray(); response.setContentLength(buf.length); sos.write(buf); //锟斤拷锟斤拷锟缴碉拷锟斤拷证锟斤拷图片写锟斤拷页锟斤拷 bos.close(); sos.close(); //锟斤拷锟斤拷锟缴碉拷锟斤拷证锟诫保锟芥到session session.setAttribute("rand", new String(rands)); } private void drawBackground(Graphics g) { g.setColor(new Color(0xDCDCDC)); g.fillRect(0, 0, WIDTH, HEIGHT); for (int i = 0; i < 120; i++) { int x = (int) (Math.random() * WIDTH); int y = (int) (Math.random() * HEIGHT); int red = (int) (Math.random() * 255); int green = (int) (Math.random() * 255); int blue = (int) (Math.random() * 255); g.setColor(new Color(red, green, blue)); g.drawOval(x, y, 1, 0); } } private void drawRands(Graphics g, char[] rands) { // g.setColor(Color.BLUE); Random random = new Random(); int red = random.nextInt(110); int green = random.nextInt(50); int blue = random.nextInt(50); g.setColor(new Color(red, green, blue)); g.setFont(new Font(null, Font.ITALIC | Font.BOLD, 30)); g.drawString("" + rands[0], 5, 35); g.drawString("" + rands[1], 25, 34); g.drawString("" + rands[2], 45, 36); g.drawString("" + rands[3], 65, 33); } private char[] generateCheckCode() { String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char[] rands = new char[4]; for (int i = 0; i < 4; i++) { int rand = (int) (Math.random() * 36); rands[i] = chars.charAt(rand); } return rands; } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
3,在代码中多使用try...catch...,如果出现问题则抛异常;在前端页面显示时,如果出现问题统一跳转到一个报错页面;
package com.lq.dao; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import com.lq.bean.CiTiao; public class QueryFromMySql { private static String DriverName="com.mysql.jdbc.Driver"; private static String UName="root"; private static String Upwd="root"; private static String Url="jdbc:mysql://192.168.25.1:3306/xinjian?useUnicode=true&characterEncoding=UTF-8"; public int query() //查询词条总数 { Connection conn=null; PreparedStatement pstmt=null; ResultSet result=null; int count=-1; try { Class.forName(DriverName); conn=DriverManager.getConnection(Url, UName, Upwd); String sql="select count(*) from citiao"; pstmt= conn.prepareStatement(sql); result=pstmt.executeQuery(sql); result.next(); count=result.getInt(1); return count; } catch(ClassNotFoundException e) { e.printStackTrace(); return count; } catch (SQLException e) { e.printStackTrace(); return count; } catch(Exception e) { e.printStackTrace(); return count; } finally { try { if(result!=null) result.close(); if(pstmt!=null) pstmt.close(); if(conn!=null) conn.close(); } catch(SQLException e) { e.printStackTrace(); } } } public List<CiTiao> SearchList() //查询所有的词条信息 { List<CiTiao> CiTiaos=new ArrayList<CiTiao>(); CiTiao CiTiao=null; Connection conn=null; PreparedStatement pstmt=null; ResultSet result=null; try { Class.forName(DriverName); conn=DriverManager.getConnection(Url, UName, Upwd); String sql="select * from citiao limit 0,50 "; pstmt= conn.prepareStatement(sql); result=pstmt.executeQuery(); while(result.next()) { int id=result.getInt("id"); //词条编号1 String name=result.getString("name"); //词条名称2 String des=result.getString("des"); //词条简单内容3 String url=result.getString("url"); //词条链接4 CiTiao=new CiTiao(id,name,des,url); CiTiaos.add(CiTiao); } return CiTiaos; } catch(ClassNotFoundException e) { e.printStackTrace(); return null; } catch (SQLException e) { e.printStackTrace(); return null; } catch(Exception e) { e.printStackTrace(); return null; } finally { try { if(result!=null) result.close(); if(pstmt!=null) pstmt.close(); if(conn!=null) conn.close(); } catch(SQLException e) { e.printStackTrace(); } } } public List<CiTiao> SearchByName(String name) //根据名称查询所有的词条信息 { List<CiTiao> CiTiaos=new ArrayList<CiTiao>(); CiTiao CiTiao=null; Connection conn=null; PreparedStatement pstmt=null; ResultSet result=null; try { Class.forName(DriverName); conn=DriverManager.getConnection(Url, UName, Upwd); String sql="select * from citiao where name like ?"; pstmt= conn.prepareStatement(sql); pstmt.setString(1,"%"+name+"%"); result=pstmt.executeQuery(); while(result.next()) { name=result.getString("name"); //词条名称2 String des=result.getString("des"); //词条简单内容3 String url=result.getString("url"); //词条链接4 CiTiao=new CiTiao(name,des,url); CiTiaos.add(CiTiao); } return CiTiaos; } catch(ClassNotFoundException e) { e.printStackTrace(); return null; } catch (SQLException e) { e.printStackTrace(); return null; } catch(Exception e) { e.printStackTrace(); return null; } finally { try { if(result!=null) result.close(); if(pstmt!=null) pstmt.close(); if(conn!=null) conn.close(); } catch(SQLException e) { e.printStackTrace(); } } } public List<CiTiao> SearchByDes(String des) //根据分类查询所有的词条信息 { List<CiTiao> CiTiaos=new ArrayList<CiTiao>(); CiTiao CiTiao=null; Connection conn=null; PreparedStatement pstmt=null; ResultSet result=null; try { Class.forName(DriverName); conn=DriverManager.getConnection(Url, UName, Upwd); String sql="select * from citiao where des like ?"; pstmt= conn.prepareStatement(sql); pstmt.setString(1,"%"+des+"%"); result=pstmt.executeQuery(); while(result.next()) { String name=result.getString("name"); //词条名称2 des=result.getString("des"); //词条简单内容3 String url=result.getString("url"); //词条链接4 CiTiao=new CiTiao(name,des,url); CiTiaos.add(CiTiao); } return CiTiaos; } catch(ClassNotFoundException e) { e.printStackTrace(); return null; } catch (SQLException e) { e.printStackTrace(); return null; } catch(Exception e) { e.printStackTrace(); return null; } finally { try { if(result!=null) result.close(); if(pstmt!=null) pstmt.close(); if(conn!=null) conn.close(); } catch(SQLException e) { e.printStackTrace(); } } } public static void main(String[] args) { QueryFromMySql queryFromMySql=new QueryFromMySql(); //queryFromMySql.QueryBySend_time(); } }
4,如果用户不进行注册直接访问某个中间网页时,则提示登录;
5,页面与页面之间跳转的Cookie中有隐蔽信息的设置为HttpOnly属性避免XSS攻击;
response.addHeader("Set-Cookie", "uid=112; Path=/; HttpOnly")
等等