1, first of all, briefly talk about the development of the regular Web login module (for simple login function, the database fields are not encrypted and encrypted during transmission)
Non-Secure Login module development
Using Jsp+mysql
The database table looks like this:
Use JSP page to create login.jsp and index.jsp page (for the convenience of explanation, directly using JSP page value and check) the specific code is as follows:
<%@ page language= "java" contenttype= "text/html; Charset=utf-8 " pageencoding=" UTF-8 "%><! DOCTYPE HTML PUBLIC "-//w3c//dtd HTML 4.01 transitional//en" "Http://www.w3.org/TR/html4/loose.dtd" > account No: <input type= "text" name= "username"/><br/> dense & nbsp, Code: <input type= "password" name= "password" ><br/><br/> <input type= "Submit" value= "Submit" ><br/></form></body>
<% @pageImport= "Java.sql.ResultSet"%><% @pageImport= "Java.sql.PreparedStatement"%><% @pageImport= "Java.sql.DriverManager"%><% @pageImport= "java.sql.Connection"%><%@ page language= "java" contenttype= "text/html; Charset=utf-8 "pageencoding= "UTF-8"%><! DOCTYPE HTML PUBLIC "-//w3c//dtd HTML 4.01 transitional//en" "Http://www.w3.org/TR/html4/loose.dtd" >//get MySQL Connection objectString driverclass= "Com.mysql.jdbc.Driver"; String User= "Root"; String PSW= "Zwkkwz"; String URL= "Jdbc:mysql://localhost:3306/mytest"; Class.forName (Driverclass); Connection Conn=drivermanager.getconnection (URL,USER,PSW); //get login.jsp's username and password .String Username=request.getparameter ("username"); String Password=request.getparameter ("Password"); String SQL= "SELECT * from login where username=?"; PreparedStatement stmt=conn.preparestatement (SQL); Stmt.setstring (1, username); ResultSet RS=stmt.executequery ();%><%if(Rs.next ()) {String P=rs.getstring ("Password"); if(Password.equals (p)) {out.println ("User" +username+ "Login Successful"); }Else{out.println ("User" +username+ "Login Failed"); } }Else{out.println ("User" +username+ "does not exist"); }%></body>
Through the above two JSP pages to implement the login page, you can implement the verification function. But there are too many security concerns.
- The database is stored in clear text
- Data is not encrypted during transfer (you can use the Wireshark tool to get the clear text of post delivery
2, next to the above two issues for analysis and resolution:
Security Hardening 1: Digest The password field of the database table (data digest processing in MySQL, SQL statements as follows)
// using SHA for digest processing UPDATE = SHA (password) // using MD5 for digest processing UPDATE Set = MD5 (password)
The original plaintext 123456 after is encrypted with MD5 is e10adc3949ba59abbe56e057f20f883e
But this is still not safe, enter http://www.cmd5.com/encrypted ciphertext after decryption can get plaintext password
- For example, the database has more than one password clear text is 123456, the ciphertext generated by MD5 encryption is identical, so that others can be decrypted to obtain the same password
- In response to the above problems, we will add salt treatment. That is, at the time of user registration, randomly generate a specified length of the field, and then combined with the user password, in the MD5 encryption, etc., will discuss this issue.
When the plaintext password of the database is MD5 encrypted, we can change the processing logic of the JSP page, and then verify the password that the user entered is MD5 processed.
- Write a tool class Digestutil, by this tool class to help us generate user input password corresponding MD5
- Write a tool class bytestostring, convert the byte array to a string
- The specific code is as follows, the specific process please the reader to analyze the code
Packageutil;Importjava.security.MessageDigest;Importjava.security.NoSuchAlgorithmException; Public classDigestutil { Public StaticString GetMD5 (byte[] data)throwsnosuchalgorithmexception{messagedigest MD= Messagedigest.getinstance ("MD5"); Md.update (data); byte[] Resultbytes =md.digest (); String resultstring=bytestostring.frombytestostring (resultbytes); returnresultstring; } Public StaticString getSHA1 (byte[] data)throwsnosuchalgorithmexception{messagedigest MD= Messagedigest.getinstance ("SHA1"); Md.update (data); byte[] Resultbytes =md.digest (); String resultstring=bytestostring.frombytestostring (resultbytes); returnresultstring; }}
Packageutil; Public classbytestostring { Public StaticString frombytestostring (byte[] resultbytes) {StringBuilder Builder=NewStringBuilder (); for(inti = 0; i < resultbytes.length; i++) { if(Integer.tohexstring (0xFF & Resultbytes[i]). Length () = = 1) {builder.append ("0"). Append (Integer.tohexstring (0xFF &resultbytes[i])); } Else{builder.append (integer.tohexstring (0xFF &resultbytes[i])); } } returnbuilder.tostring (); }}
The modified index.jsp code is as follows:
<% @pageImport= "util." Digestutil "%><% @pageImport= "Java.sql.ResultSet"%><% @pageImport= "Java.sql.PreparedStatement"%><% @pageImport= "Java.sql.DriverManager"%><% @pageImport= "java.sql.Connection"%><%@ page language= "java" contenttype= "text/html; Charset=utf-8 "pageencoding= "UTF-8"%><! DOCTYPE HTML PUBLIC "-//w3c//dtd HTML 4.01 transitional//en" "Http://www.w3.org/TR/html4/loose.dtd" >//get MySQL Connection objectString driverclass= "Com.mysql.jdbc.Driver"; String User= "Root"; String PSW= "Zwkkwz"; String URL= "Jdbc:mysql://localhost:3306/mytest"; Class.forName (Driverclass); Connection Conn=drivermanager.getconnection (URL,USER,PSW); //get login.jsp's username and password .String Username=request.getparameter ("username"); String Password=request.getparameter ("Password"); String SQL= "SELECT * from login where username=?"; PreparedStatement stmt=conn.preparestatement (SQL); Stmt.setstring (1, username); ResultSet RS=stmt.executequery ();%><%if(Rs.next ()) {String P=rs.getstring ("Password"); //Simple Clear-text check code /*if (Password.equals (p)) {out.println ("user" +username+ "login Successful"); }else{out.println ("user" +username+ "Login Failed"); }}else{out.println ("user" +username+ "does not exist"); } */ //SQL uses MD5 encrypted ciphertext and user-entered password checksum code if(P.equals (DIGESTUTIL.GETMD5 (Password.getbytes () )))//getMD5 (byte[] data) method is to convert the original data into encrypted ciphertext{out.println ("Database Password field" +p); Out.println ("User-entered password" +password); Out.println ("Treated password" +digestutil.getmd5 (Password.getbytes ())); Out.println ("User" +username+ "Login Successful"); }Else{out.println ("User" +username+ "Login Failed"); } }Else{out.println ("User" +username+ "does not exist"); }%></body>
Through the above steps, we only have a simple MD5 encryption for the password of the database, with the following disadvantages:
- It is easy to infer the algorithm based on the number of cipher bits, thus using tool cracking
- Real passwords are the same, encrypted passwords are the same
Next, let's introduce the salt treatment:
3, add salt treatment, in order to enhance the complexity of the system, and then through the digest processing, you can get more hidden digest value
- Optionally enter the Salt field in the table ABCCBA, then combine with the original plaintext password 123456, and then do SHA1 encryption
- build a pair of data , Enter the Salt field in the table CBAABC, and then combine with the original plaintext password 123456, and then do SHA1 encryption
The so-called salt field is a random field, the specific random algorithm is not discussed, each time the user registers an account, the background will give it randomly generated a different field
Then, according to the Password and Salt field combined to digest processing, there is a database table in the Password field, so that the original plaintext is 123456 generated ciphertext is not the same
The operation is as follows:
Ciphertext is encrypted (the original password is 123456):
Next, Index.jsp's processing logic is transformed, and the tool class SHA1 processed for user-entered passwords is listed in the Digestutil method above.
The index.jsp code is as follows:
<% @pageImport= "util." Digestutil "%><% @pageImport= "Java.sql.ResultSet"%><% @pageImport= "Java.sql.PreparedStatement"%><% @pageImport= "Java.sql.DriverManager"%><% @pageImport= "java.sql.Connection"%><%@ page language= "java" contenttype= "text/html; Charset=utf-8 "pageencoding= "UTF-8"%><! DOCTYPE HTML PUBLIC "-//w3c//dtd HTML 4.01 transitional//en" "Http://www.w3.org/TR/html4/loose.dtd" >//get MySQL Connection objectString driverclass= "Com.mysql.jdbc.Driver"; String User= "Root"; String PSW= "Zwkkwz"; String URL= "Jdbc:mysql://localhost:3306/mytest"; Class.forName (Driverclass); Connection Conn=drivermanager.getconnection (URL,USER,PSW); //get login.jsp's username and password .String Username=request.getparameter ("username"); String Password=request.getparameter ("Password"); String SQL= "SELECT * from login where username=?"; PreparedStatement stmt=conn.preparestatement (SQL); Stmt.setstring (1, username); ResultSet RS=stmt.executequery ();%><%if(Rs.next ()) {String P=rs.getstring ("Password"); //SQL uses SHA1 to encrypt ciphertext and user input password checksum code//we need to get the user input password and the corresponding saltString salt=rs.getstring ("Salt"); if(P.equals (DIGESTUTIL.GETSHA1 (password+(salt). GetBytes ()))) {Out.println ("Database Password field" +p); Out.println ("User-entered password" +password); Out.println ("Treated password" +DIGESTUTIL.GETSHA1 (password+salt). GetBytes ()); Out.println ("User" +username+ "Login Successful"); }Else{out.println ("User" +username+ "Login Failed"); } }Else{out.println ("User" +username+ "does not exist"); } %> <%Rs.close (); Stmt.close (); Conn.close (); %></body>
The above steps we just encrypted the SQL operation.
In order to prevent the user from entering the password in the process of transmission is captured by the package tool, we also have to encrypt the password transmission process, so that can be obtained is also ciphertext.
Use Md5.js to encrypt forms (can Baidu search md5.js download)
Transport encryption: Data is encrypted before it is sent out on the browser side.
Introducing Md5.js in JSP, assigning an ID to the input tag, and then given a method onclick at the time of submission, to encrypt the password entered by the user, specifically login.jsp as follows:
<%@ page language= "java" contenttype= "text/html; Charset=utf-8 "pageencoding= "UTF-8"%><! DOCTYPE HTML PUBLIC "-//w3c//dtd HTML 4.01 transitional//en" "Http://www.w3.org/TR/html4/loose.dtd" >Account No.: <input type= "text" name= "username"/><br/>Dense code: <input type= "password" name= "password" id= "password" ><br/><br/> <input type= "Submi T "value=" submit "onclick=" ToMd5 () "><br/></form></body><script type=" Text/javascript ">function ToMd5 () {var passwordnode=document.getelementbyid ("Password"); //before Encryptionalert (passwordnode.value); var hash=hex_md5 (Passwordnode.value); Passwordnode.value=Hash; //after encryptionalert (passwordnode.value); }</script>