mirror of
				https://github.com/ZSCNetSupportDept/WechatTicketSystem.git
				synced 2025-10-31 02:16:18 +08:00 
			
		
		
		
	use RSA to encrypt login
This commit is contained in:
		| @@ -62,7 +62,7 @@ public class Authorize extends HttpServlet { | ||||
| 			l = System.currentTimeMillis(); | ||||
| 		} | ||||
|  | ||||
| 		if (!Checker.nonNull(c, l)) { | ||||
| 		if (Checker.hasNull(c, l)) { | ||||
| 			return new Response(Response.ResponseCode.AUTHORIZE_FAILED); | ||||
| 		} | ||||
| 		if (l < System.currentTimeMillis() - Settings.I.User_Command_Timeout * 1000) { | ||||
|   | ||||
| @@ -28,7 +28,7 @@ import java.io.PrintWriter; | ||||
|  * Don't modify this source without my agreement | ||||
|  * *********************************************** | ||||
|  */ | ||||
| @WebServlet(name = "QueryTicket", urlPatterns = "/api/ticketquery", loadOnStartup = 24) | ||||
| @WebServlet(name = "TicketQuery", urlPatterns = "/api/ticketquery", loadOnStartup = 24) | ||||
| public class TicketQuery extends HttpServlet { | ||||
|  | ||||
| 	private Gson gson = SQLCore.gson; | ||||
|   | ||||
| @@ -49,7 +49,7 @@ public class Login extends HttpServlet { | ||||
| 		String wechat = request.getParameter("wechat"); | ||||
| 		String opId = request.getParameter("op"); | ||||
| 		String password = request.getParameter("pass"); | ||||
| 		if (Checker.nonNull(wechat, opId, password)) return new Response(Response.ResponseCode.PARAMETER_REQUIRED); | ||||
| 		if (Checker.hasNull(wechat, opId, password)) return new Response(Response.ResponseCode.PARAMETER_REQUIRED); | ||||
|  | ||||
| 		try (Session s = SQLCore.sf.openSession()) { | ||||
| 			Operator operator = s.get(Operator.class, Integer.parseInt(opId)); | ||||
| @@ -63,7 +63,7 @@ public class Login extends HttpServlet { | ||||
| 			HttpSession httpSession = request.getSession(true); | ||||
| 			httpSession.setAttribute("wechat", wechat); | ||||
| 			httpSession.setAttribute("operator", operator); | ||||
| 			return new Response(Response.ResponseCode.OK); | ||||
| 			return new Response(Response.ResponseCode.OK, operator); | ||||
| 		} catch (NumberFormatException e) { | ||||
| 			return new Response(Response.ResponseCode.ILLEGAL_PARAMETER); | ||||
| 		} catch (HibernateException e) { | ||||
|   | ||||
| @@ -0,0 +1,10 @@ | ||||
| package love.sola.netsupport.api.admin; | ||||
|  | ||||
| /** | ||||
|  * *********************************************** | ||||
|  * Created by Sola on 2015/12/13. | ||||
|  * Don't modify this source without my agreement | ||||
|  * *********************************************** | ||||
|  */ | ||||
| public class TicketQuery { | ||||
| } | ||||
| @@ -0,0 +1,82 @@ | ||||
| package love.sola.netsupport.api.admin; | ||||
|  | ||||
| import com.google.gson.Gson; | ||||
| import love.sola.netsupport.api.Response; | ||||
| import love.sola.netsupport.pojo.Operator; | ||||
| import love.sola.netsupport.pojo.Ticket; | ||||
| import love.sola.netsupport.sql.SQLCore; | ||||
| import love.sola.netsupport.util.Checker; | ||||
| import love.sola.netsupport.util.ParseUtil; | ||||
| import org.hibernate.HibernateException; | ||||
| import org.hibernate.Session; | ||||
|  | ||||
| import javax.servlet.ServletException; | ||||
| 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; | ||||
| import java.io.IOException; | ||||
| import java.io.PrintWriter; | ||||
|  | ||||
| /** | ||||
|  * *********************************************** | ||||
|  * Created by Sola on 2015/12/13. | ||||
|  * Don't modify this source without my agreement | ||||
|  * *********************************************** | ||||
|  */ | ||||
| @WebServlet(name = "TicketUpdate", urlPatterns = "/api/ticketupdate", loadOnStartup = 32) | ||||
| public class TicketUpdate extends HttpServlet { | ||||
|  | ||||
| 	private Gson gson = SQLCore.gson; | ||||
|  | ||||
| 	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | ||||
| 		doGet(request, response); | ||||
| 	} | ||||
|  | ||||
| 	@SuppressWarnings("Duplicates") | ||||
| 	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | ||||
| 		request.setCharacterEncoding("utf-8"); | ||||
| 		response.setCharacterEncoding("utf-8"); | ||||
| 		response.addHeader("Content-type", "text/json;charset=utf-8"); | ||||
| 		PrintWriter out = response.getWriter(); | ||||
| 		String json = gson.toJson(update(request)); | ||||
| 		out.println(ParseUtil.parseJsonP(request, json)); | ||||
| 		out.close(); | ||||
| 	} | ||||
|  | ||||
| 	private Response update(HttpServletRequest request) { | ||||
| 		String ticket = request.getParameter("ticket"); | ||||
| 		String remark = request.getParameter("remark"); | ||||
| 		String status = request.getParameter("status"); | ||||
| 		if (Checker.hasNull(ticket, remark, status)) return new Response(Response.ResponseCode.PARAMETER_REQUIRED); | ||||
|  | ||||
| 		try (Session s = SQLCore.sf.openSession()) { | ||||
| 			HttpSession httpSession = request.getSession(false); | ||||
| 			if (!Checker.operator(httpSession)) { | ||||
| 				return new Response(Response.ResponseCode.UNAUTHORIZED); | ||||
| 			} | ||||
| 			Operator op = (Operator) httpSession.getAttribute("operator"); | ||||
| 			Ticket t = s.get(Ticket.class, Integer.parseInt(ticket)); | ||||
| 			if (t == null) { | ||||
| 				return new Response(Response.ResponseCode.TICKET_NOT_FOUND); | ||||
| 			} | ||||
| 			t.setOperator(op); | ||||
| 			t.setRemark(remark); | ||||
| 			t.setStatus(Integer.parseInt(status)); | ||||
| 			s.beginTransaction(); | ||||
| 			s.update(t); | ||||
| 			s.getTransaction().commit(); | ||||
| 			return new Response(Response.ResponseCode.OK, t); | ||||
| 		} catch (NumberFormatException e) { | ||||
| 			return new Response(Response.ResponseCode.ILLEGAL_PARAMETER); | ||||
| 		} catch (HibernateException e) { | ||||
| 			e.printStackTrace(); | ||||
| 			return new Response(Response.ResponseCode.DATABASE_ERROR, e); | ||||
| 		} catch (Exception e) { | ||||
| 			e.printStackTrace(); | ||||
| 			return new Response(Response.ResponseCode.INTERNAL_ERROR, e); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -4,6 +4,8 @@ import lombok.AllArgsConstructor; | ||||
| import lombok.Data; | ||||
| import lombok.NoArgsConstructor; | ||||
| import love.sola.netsupport.sql.TableTicket; | ||||
| import org.hibernate.envers.Audited; | ||||
| import org.hibernate.envers.RelationTargetAuditMode; | ||||
|  | ||||
| import javax.persistence.*; | ||||
| import java.util.Date; | ||||
| @@ -19,6 +21,7 @@ import java.util.Date; | ||||
| @NoArgsConstructor | ||||
| @Entity | ||||
| @Table(name = "tickets") | ||||
| @Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED) | ||||
| public class Ticket { | ||||
|  | ||||
| 	public static final String PROPERTY_USER = "user"; | ||||
|   | ||||
| @@ -1,51 +0,0 @@ | ||||
| package love.sola.netsupport.util; | ||||
|  | ||||
| import org.apache.commons.codec.binary.Base64; | ||||
|  | ||||
| import javax.crypto.Cipher; | ||||
| import javax.crypto.spec.IvParameterSpec; | ||||
| import javax.crypto.spec.SecretKeySpec; | ||||
| import java.nio.charset.StandardCharsets; | ||||
|  | ||||
| public class AESUtil { | ||||
|  | ||||
| 	public static final byte[] initVector   =   "RandomInitVector".getBytes(StandardCharsets.UTF_8); | ||||
| 	public static final byte[] key          =   "$bitch@sola.love".getBytes(StandardCharsets.UTF_8); | ||||
|  | ||||
| 	public static String encrypt(String value) { | ||||
|         try { | ||||
|             IvParameterSpec iv = new IvParameterSpec(initVector); | ||||
|             SecretKeySpec skeySpec = new SecretKeySpec(key, "AES"); | ||||
|  | ||||
|             Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); | ||||
|             cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); | ||||
|  | ||||
|             byte[] encrypted = cipher.doFinal(value.getBytes()); | ||||
|  | ||||
|             return Base64.encodeBase64String(encrypted); | ||||
|         } catch (Exception ex) { | ||||
|             ex.printStackTrace(); | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public static String decrypt(String encrypted) { | ||||
|         try { | ||||
|             IvParameterSpec iv = new IvParameterSpec(initVector); | ||||
|             SecretKeySpec skeySpec = new SecretKeySpec(key, "AES"); | ||||
|  | ||||
|             Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); | ||||
|             cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); | ||||
|  | ||||
|             byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted)); | ||||
|  | ||||
|             return new String(original); | ||||
|         } catch (Exception ex) { | ||||
|             ex.printStackTrace(); | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -12,13 +12,17 @@ import javax.servlet.http.HttpSession; | ||||
|  */ | ||||
| public class Checker { | ||||
|  | ||||
| 	public static boolean nonNull(Object... v) { | ||||
| 		for (Object o : v) if (o == null) return false; | ||||
| 		return true; | ||||
| 	public static boolean hasNull(Object... v) { | ||||
| 		for (Object o : v) if (o == null) return true; | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	public static boolean authorized(HttpSession s, Command c) { | ||||
| 		return s != null && s.getAttribute("authorized") == c; | ||||
| 	} | ||||
|  | ||||
| 	public static boolean operator(HttpSession s) { | ||||
| 		return s != null && s.getAttribute("operator") != null; | ||||
| 	} | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -15,7 +15,7 @@ public class Crypto { | ||||
| 	} | ||||
|  | ||||
| 	public static boolean check(String plain, String hash) { | ||||
| 		return BCrypt.checkpw(AESUtil.decrypt(plain), hash); | ||||
| 		return BCrypt.checkpw(RSAUtil.decrypt(plain), hash); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -23,11 +23,9 @@ public class ParseUtil { | ||||
| 				.append(lang("Ticket_Info_Id")).append(t.getId()).append("\n") | ||||
| 				.append(lang("Ticket_Info_Desc")).append(t.getDescription()).append("\n") | ||||
| 				.append(lang("Ticket_Info_Submit_Time")).append(dateFormat.format(t.getSubmitTime())).append("\n"); | ||||
| 		if (t.getUpdateTime() != null) { | ||||
| 			sb.append(lang("Ticket_Info_Operator")).append(t.getOperator().getId()).append("\n"); | ||||
| 			sb.append(lang("Ticket_Info_Remark")).append(t.getRemark()).append("\n"); | ||||
| 			sb.append(lang("Ticket_Info_Update_Time")).append(dateFormat.format(t.getUpdateTime())).append("\n"); | ||||
| 		} | ||||
| 		if (t.getOperator() != null) sb.append(lang("Ticket_Info_Operator")).append(t.getOperator().getId()).append("\n"); | ||||
| 		if (t.getRemark() != null) sb.append(lang("Ticket_Info_Remark")).append(t.getRemark()).append("\n"); | ||||
| 		if (t.getUpdateTime() != null) sb.append(lang("Ticket_Info_Update_Time")).append(dateFormat.format(t.getUpdateTime())).append("\n"); | ||||
| 		sb.append(lang("Ticket_Info_Status")).append(Status.getLocalized(t.getStatus())); | ||||
| 		return sb.toString(); | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										61
									
								
								src/main/java/love/sola/netsupport/util/RSAUtil.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/main/java/love/sola/netsupport/util/RSAUtil.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | ||||
| package love.sola.netsupport.util; | ||||
|  | ||||
| import org.apache.commons.codec.binary.Base64; | ||||
|  | ||||
| import javax.crypto.Cipher; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| import java.security.Key; | ||||
| import java.security.KeyPair; | ||||
| import java.security.KeyPairGenerator; | ||||
|  | ||||
| public class RSAUtil { | ||||
|  | ||||
|  | ||||
| 	public static Key publicKey; | ||||
| 	public static Key privateKey; | ||||
| 	public static String publicKey_s; | ||||
| 	public static String privateKey_s; | ||||
|  | ||||
|     static { | ||||
| 	    genKeyPair(); | ||||
|     } | ||||
|  | ||||
| 	public static void genKeyPair() { | ||||
| 		try { | ||||
| 			KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); | ||||
| 			kpg.initialize(1024); | ||||
| 			KeyPair kp = kpg.genKeyPair(); | ||||
| 			publicKey = kp.getPublic(); | ||||
| 			privateKey = kp.getPrivate(); | ||||
| 			publicKey_s = Base64.encodeBase64String(publicKey.getEncoded()); | ||||
| 			privateKey_s = Base64.encodeBase64String(privateKey.getEncoded()); | ||||
| 		} catch (Exception e) { | ||||
| 			e.printStackTrace(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public static String encrypt(String value) { | ||||
|         try { | ||||
| 	        Cipher cipher = Cipher.getInstance("RSA"); | ||||
| 	        cipher.init(Cipher.ENCRYPT_MODE, publicKey); | ||||
| 	        byte[] encrypted = cipher.doFinal(value.getBytes(StandardCharsets.UTF_8)); | ||||
| 	        return Base64.encodeBase64String(encrypted); | ||||
|         } catch (Exception ex) { | ||||
|             ex.printStackTrace(); | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public static String decrypt(String encrypted) { | ||||
|         try { | ||||
|             Cipher cipher = Cipher.getInstance("RSA"); | ||||
| 	        cipher.init(Cipher.DECRYPT_MODE, privateKey); | ||||
|             byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted)); | ||||
| 	        return new String(original, StandardCharsets.UTF_8); | ||||
|         } catch (Exception ex) { | ||||
|             ex.printStackTrace(); | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,6 +1,7 @@ | ||||
| package love.sola.netsupport.wechat.handler; | ||||
|  | ||||
| import love.sola.netsupport.sql.TableOperator; | ||||
| import love.sola.netsupport.util.RSAUtil; | ||||
| import me.chanjar.weixin.common.exception.WxErrorException; | ||||
| import me.chanjar.weixin.common.session.WxSessionManager; | ||||
| import me.chanjar.weixin.mp.api.WxMpMessageHandler; | ||||
| @@ -28,7 +29,7 @@ public class LoginHandler implements WxMpMessageHandler { | ||||
| 		if (!TableOperator.has(wxMessage.getFromUserName())) { | ||||
| 			return out.content(lang("Not_Operator")).build(); | ||||
| 		} else { | ||||
| 			return out.content(format("Operator_Login_Link", wxMessage.getFromUserName())).build(); | ||||
| 			return out.content(format("Operator_Login_Link", wxMessage.getFromUserName(), RSAUtil.publicKey_s)).build(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Sola
					Sola