之前發了一個登入表的設計,這裡是設計實現的程式碼:網站登入設計
阿新 • • 發佈:2018-12-19
簡單的使用者表設計如上圖:
程式碼如下所示: 隨機加密演算法6個:
package com.auth.sp.common.utils; import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; import sun.misc.BASE64Encoder; import java.security.Key; import java.security.MessageDigest; import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; /** * 作者: 薛俊鵬 * 時間:2018/10/15 on 17:12 . * 描述:演算法中心 * 內容:這裡記錄描述了N種需要金鑰的演算法 * 每種演算法都會有一個特定的標識,根據標識鎖定演算法,最後在由MD5加密一次,加密的結果都保留大寫 * 狀態: 編寫/修改 */ public class AlgorithmCenter { /**金鑰演算法**/ public static final String KEY_ALGORITHM = "AES"; /**加解密演算法/工作模式/填充方式**/ public static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding"; private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; /** * 加密資料 ral=1 * @param data 待加密資料 * @param key 金鑰 16位 * @return 加密後的資料 * */ public static String AESencrypt1(String data, String key) throws Exception { Key k = new SecretKeySpec(key.getBytes("UTF-8"), KEY_ALGORITHM); Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); //例項化Cipher物件,它用於完成實際的加密操作 cipher.init(Cipher.ENCRYPT_MODE, k); //初始化Cipher物件,設定為加密模式 return Base64.encode(cipher.doFinal(data.getBytes("UTF-8"))); //執行加密操作。加密後的結果用Base64編碼進行傳輸 } /** ral = 1 end **/ /** * 加密 ral=2 * @param content * 需要加密的內容 * @return */ public static String AESencrypt2(String content,String key) { try { Cipher cipher = Cipher.getInstance("AES");// 建立密碼器 byte[] byteContent = content.getBytes("utf-8"); cipher.init(Cipher.ENCRYPT_MODE, genKey(key));// 初始化 byte[] result = cipher.doFinal(byteContent); return parseByte2HexStr(result); // 加密 } catch (Exception e) { e.printStackTrace(); } return null; } /** * @mock 根據金鑰獲得 SecretKeySpec * @param strKey 加密解密金鑰 * @return */ private static SecretKeySpec genKey(String strKey){ byte[] enCodeFormat = {0}; try { KeyGenerator kgen = KeyGenerator.getInstance("AES"); SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" ); secureRandom.setSeed(strKey.getBytes()); kgen.init(128, secureRandom); SecretKey secretKey = kgen.generateKey(); enCodeFormat = secretKey.getEncoded(); } catch (Exception e) { e.printStackTrace(); } return new SecretKeySpec(enCodeFormat, "AES"); } /** * 將二進位制轉換成16進位制 * @param buf * @return */ private static String parseByte2HexStr(byte buf[]) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < buf.length; i++) { String hex = Integer.toHexString(buf[i] & 0xFF); if (hex.length() == 1) { hex = '0' + hex; } sb.append(hex.toUpperCase()); } return sb.toString(); } /** ral = 2 end **/ /** * MD5加密 生成32位md5碼 */ public static String AESencrypt3(String inStr,String key){ MessageDigest md5 = null; try{ md5 = MessageDigest.getInstance("MD5"); }catch (Exception e){ e.printStackTrace(); return ""; } char[] charArray = inStr.toCharArray(); byte[] byteArray = new byte[charArray.length]; for (int i = 0; i < charArray.length; i++) byteArray[i] = (byte) charArray[i]; byte[] md5Bytes = md5.digest(byteArray); StringBuffer hexValue = new StringBuffer(); for (int i = 0; i < md5Bytes.length; i++){ int val = ((int) md5Bytes[i]) & 0xff; if (val < 16) hexValue.append("0"); hexValue.append(Integer.toHexString(val)); } return (hexValue.toString()+key).toUpperCase(); } /** ral = 3 end **/ /** * base64加密 生成32位md5碼 */ public static String AESencrypt4(String content,String key){ byte[] bt = content.getBytes(); String str = (new BASE64Encoder()).encodeBuffer(bt); return (str.trim()+key).toUpperCase(); } /** ral = 4 end **/ /** * Takes the raw bytes from the digest and formats them correct. * * @param bytes the raw bytes from the digest. * @return the formatted bytes. */ private static String getFormattedText(byte[] bytes) { int len = bytes.length; StringBuilder buf = new StringBuilder(len * 2); // 把密文轉換成十六進位制的字串形式 for (int j = 0; j < len; j++) { buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]); buf.append(HEX_DIGITS[bytes[j] & 0x0f]); } return buf.toString().toUpperCase(); } public static String AESencrypt5(String content,String key) { if (content == null) { return null; } try { MessageDigest messageDigest = MessageDigest.getInstance("SHA1"); messageDigest.update(content.getBytes()); return (getFormattedText(messageDigest.digest())+key); } catch (Exception e) { throw new RuntimeException(e); } } /** ral = 5 end **/ /** * 利用java原生的摘要實現SHA256加密 * @param str 加密後的報文 * @return */ public static String AESencrypt6(String content,String key){ MessageDigest messageDigest; String encodeStr = ""; try { messageDigest = MessageDigest.getInstance("SHA-256"); messageDigest.update(content.getBytes("UTF-8")); encodeStr = byte2Hex(messageDigest.digest()); } catch (Exception e) { e.printStackTrace(); } return (encodeStr+key).toUpperCase(); } /** * 將byte轉為16進位制 * @param bytes * @return */ private static String byte2Hex(byte[] bytes){ StringBuffer stringBuffer = new StringBuffer(); String temp = null; for (int i=0;i<bytes.length;i++){ temp = Integer.toHexString(bytes[i] & 0xFF); if (temp.length()==1){ //1得到一位的進行補0操作 stringBuffer.append("0"); } stringBuffer.append(temp); } return stringBuffer.toString(); } /** ral = 6 end **/ /*資料加密開始*/ public static String GetAES(String value,int rand) throws Exception{ /*返回資料:加密資料+#+金鑰*/ String key_vue = ""; /*金鑰*/ String km = ""; GetKey key = new GetKey(); switch (rand){ case 1: km = key.KeyValue16(); key_vue = ToMD5.MD5(AESencrypt1(value,km))+"#"+km; break; case 2: km = key.KeyValue32(); key_vue = ToMD5.MD5(AESencrypt2(value,km))+"#"+km; break; case 3: km = key.KeyValue32(); key_vue = ToMD5.MD5(AESencrypt3(value,km))+"#"+km; break; case 4: km = key.KeyValue32(); key_vue = ToMD5.MD5(AESencrypt4(value,km))+"#"+km; break; case 5: km = key.KeyValue32(); key_vue = ToMD5.MD5(AESencrypt5(value,km))+"#"+km; break; case 6: km = key.KeyValue32(); key_vue = ToMD5.MD5(AESencrypt6(value,km))+"#"+km; break; default: km = key.KeyValue32(); key_vue = ToMD5.MD5("JIAMISHUJUCUOWU")+"#"+km; break; } return key_vue; } /*資料加密開始,加密資料,演算法,金鑰*/ public static String GetAESEnd(String value,int rand,String km) throws Exception{ /*返回資料:加密資料*/ String key_vue = ""; switch (rand){ case 1: key_vue = ToMD5.MD5(AESencrypt1(value,km)); break; case 2: key_vue = ToMD5.MD5(AESencrypt2(value,km)); break; case 3: key_vue = ToMD5.MD5(AESencrypt3(value,km)); break; case 4: key_vue = ToMD5.MD5(AESencrypt4(value,km)); break; case 5: key_vue = ToMD5.MD5(AESencrypt5(value,km)); case 6: key_vue = ToMD5.MD5(AESencrypt6(value,km)); break; default: key_vue = ToMD5.MD5("JIAMISHUJUCUOWU"); break; } return key_vue; } }
轉MD5:
package com.auth.sp.common.utils; import java.security.MessageDigest; /** * 作者: 薛俊鵬 * 時間:2018/10/15 on 17:19 . * 描述:MD5演算法 * 內容: * 狀態: 編寫/修改 */ public class ToMD5 { public static String MD5(String key) { char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; try { byte[] btInput = key.getBytes(); // 獲得MD5摘要演算法的 MessageDigest 物件 MessageDigest mdInst = MessageDigest.getInstance("MD5"); // 使用指定的位元組更新摘要 mdInst.update(btInput); // 獲得密文 byte[] md = mdInst.digest(); // 把密文轉換成十六進位制的字串形式 int j = md.length; char str[] = new char[j * 2]; int k = 0; for (int i = 0; i < j; i++) { byte byte0 = md[i]; str[k++] = hexDigits[byte0 >>> 4 & 0xf]; str[k++] = hexDigits[byte0 & 0xf]; } return new String(str); } catch (Exception e) { return null; } } }
登入方法:
package com.auth.sp.common.controller; import com.auth.sp.common.aspect.ClearData; import com.auth.sp.common.entity.LoginSystyem; import com.auth.sp.common.entity.PwdKey; import com.auth.sp.common.entity.SysKey; import com.auth.sp.common.entity.SysUser; import com.auth.sp.common.service.SysKeyService; import com.auth.sp.common.service.SysUserService; import com.auth.sp.common.shiro.ErrorReason; import com.auth.sp.common.shiro.Token; import com.auth.sp.common.utils.IPUtils; import com.auth.sp.common.utils.Ognl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.util.List; /** * 作者: 薛俊鵬 * 時間:2018/10/12 on 17:55 . * 描述:登陸方法及控制 資料的攔截在許可權機中處理 所有不合法的請求重置到登陸頁面 * 內容: * 狀態: 編寫/修改 */ @RestController public class LoginController { Log log = LogFactory.getLog(LoginController.class); @Autowired private SysUserService userService; @Autowired private SysKeyService keyService; /**登陸測試**/ @RequestMapping(value = "log_in",method = RequestMethod.GET) public String Login(){ List<SysUser> list = userService.SelectUser(); SysUser user = new SysUser(); for (int i = 0; i < list.size(); i++) { user = list.get(i); System.out.println("賬戶:"+user.getAccount()); } return "OK-Account"; } /**登入進入系統 全部返回json 資料**/ @RequestMapping(value = "loginUser",method = RequestMethod.POST) public String LoginUser(@ModelAttribute LoginSystyem user, ModelMap model, HttpServletRequest request, HttpServletResponse response) throws Exception{ /**使用者資訊判斷**/ if(Ognl.isEmpty(user) || Ognl.isEmpty(user.getAccount()) || Ognl.isEmpty(user.getPwd())){ /**清空物件**/ user = null; /**清空快取資料**/ response = ClearData.Clear(request,response); return ErrorReason.getErrorInfo(1).getErrorInfo();/*賬戶資訊不能為空,請重新輸入!*/ }else{ /**判斷賬戶資訊的準確性**/ SysUser u = userService.selectByAccount(user.getAccount()); /**使用者不存在**/ if(Ognl.isEmpty(u)){ /**清空物件**/ user = null; u = null; /**清空快取資料**/ response = ClearData.Clear(request,response); return ErrorReason.getErrorInfo(2).getErrorInfo();/*該賬戶資訊不存在!*/ }else{ /**存在使用者 記錄登入IP**/ u.setLogin_ip(IPUtils.getLocalIP()); userService.updateByPrimaryKeySelective(u); /**根據使用者id查詢使用者的金鑰資訊**/ SysKey sysKey = keyService.selectByUserId(u.getId()); if(Ognl.isEmpty(sysKey)){ log.info("sysKey資料異常,請及時處理!"); /**清空物件**/ user = null; sysKey = null; /**清空快取資料**/ response = ClearData.Clear(request,response); return ErrorReason.getErrorInfo(3).getErrorInfo();/*賬戶異常,請及時聯絡管理員!*/ }else{ /**密碼輸入超過5次,踢出系統,清除登陸痕跡**/ if(u.getError_time()>=5){ /**清空物件**/ user = null; user = null; sysKey = null; /**清空快取資料**/ response = ClearData.Clear(request,response); return "密碼多次輸入錯誤,"+ErrorReason.getErrorInfo(6).getErrorInfo(); }else { /**資料置換,防止SQL攻擊**/ PwdKey pwdKey = new PwdKey(); pwdKey.setKey(sysKey.getUser_key()); pwdKey.setValue(sysKey.getPwd()); pwdKey.setAccount(user.getPwd()); pwdKey.setNum(u.getAlg()); boolean isOk = SysUserController.IsPassPwd(pwdKey); /**密碼一致確認身份資訊,密碼不一致,踢出系統**/ if (!isOk) { log.info(user.getAccount() + "密碼輸入錯誤!"); /**密碼錯誤更新錯誤密碼次數**/ u.setError_time(u.getError_time() + 1); /**錯誤次數達到上限,凍結使用者**/ if (u.getError_time() >= 5) { u.setFreeze(0); u.setReason("密碼輸入錯誤次數超過5次"); } userService.updateByPrimaryKeySelective(u); /**清空物件**/ user = null; pwdKey = null; user = null; sysKey = null; /**清空快取資料**/ response = ClearData.Clear(request, response); return ErrorReason.getErrorInfo(4).getErrorInfo();/*密碼輸入錯誤*/ } else { if(u.getFreeze()==0){ /**清空物件**/ user = null; u = null; pwdKey = null; sysKey = null; /**清空快取資料**/ response = ClearData.Clear(request, response); return ErrorReason.getErrorInfo(6).getErrorInfo()+"請聯絡管理員處理!"; }else { /**更新使用者資訊**/ u.setError_time(0); u.setReason(""); userService.updateByPrimaryKeySelective(u); log.info(u.getAccount() + "歡迎進入系統..."); /**進入系統之後,全稱使用加密的身份驗證,驗證失敗,或者超時,踢出系統**/ // request.getSession().setAttribute("token", Token.EncryMacSHA(u.getAccount())); request.getSession().setAttribute("uname1",u.getAccount()); HttpSession session = request.getSession(); request.getSession().setAttribute("u",u); session.setAttribute("token",Token.EncryMacSHA(u.getAccount())); session.setAttribute("uname",u.getAccount()); pwdKey = null; user = null; sysKey = null; String result = ErrorReason.getErrorInfo(5).getErrorCode();/*授權通過*/ return result; } } } } } } } }
資料清除:
package com.auth.sp.common.aspect; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Enumeration; /** * 作者: 薛俊鵬 * 時間:2018/10/22 on 10:53 . * 描述:主要用於資料的清空和初始化處理 * 內容: * 狀態: 編寫/修改 */ public class ClearData { /**session的初始化和清空操作**/ public static void initSession(HttpServletRequest request){ /**獲取所有session 列舉**/ Enumeration em = request.getSession().getAttributeNames(); while(em.hasMoreElements()){ request.getSession().removeAttribute(em.nextElement().toString()); } } /**清空cookie**/ public static HttpServletResponse CleanCookies(HttpServletRequest request,HttpServletResponse response){ /**獲取所有cookie資訊**/ Cookie[] cookies=request.getCookies(); for(Cookie cookie: cookies){ /**使用完立即刪除**/ cookie.setMaxAge(0); /**所有路徑下的cookie**/ cookie.setPath("/"); response.addCookie(cookie); } return response; } public static HttpServletResponse Clear(HttpServletRequest request,HttpServletResponse response){ /**清空session**/ ClearData.initSession(request); request.getSession().invalidate(); /**清空cookie**/ response = ClearData.CleanCookies(request,response); return response; } }