mirror of
https://github.com/ZSCNetSupportDept/WechatTicketSystem.git
synced 2025-10-28 23:55:04 +08:00
use RSA to encrypt login
This commit is contained in:
4
pom.xml
4
pom.xml
@@ -144,6 +144,10 @@
|
||||
<version>1.0.0.Final</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-envers</artifactId>
|
||||
<version>5.0.3.Final</version>
|
||||
</dependency><dependency>
|
||||
<groupId>de.svenkubiak</groupId>
|
||||
<artifactId>jBCrypt</artifactId>
|
||||
<version>0.4</version>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,10 +40,10 @@ Not_Operator: '嘟嘟嘟……'
|
||||
|
||||
#URL
|
||||
User_Register_Link: "您尚未进行微信绑定, 请<a href=\"http://topaz.sinaapp.com/nm/v1/reg.php?wechatid={0}\">点击这里</a>进行微信绑定操作。"
|
||||
User_Query_Link: 'http://topaz.sinaapp.com/nm/v1/query.php?wechatid={0}'
|
||||
User_Query_Link: 'http://topaz.sinaapp.com/nm/v1/query.html?wechatid={0}'
|
||||
User_Submit_Link: 'http://topaz.sinaapp.com/nm/v1/rrepair.html?wechatid={0}&name={1}&isp={2}&room={3}&block={4}&phone={5}'
|
||||
Result_Page: 'http://topaz.sinaapp.com/nm/v1/result.html'
|
||||
Operator_Login_Link: '<a href=\"http://topaz.sinaapp.com/nm/v1/login.html?wechatid={0}\">CLICK HERE</a>'
|
||||
Operator_Login_Link: '<a href=\"http://topaz.sinaapp.com/nm/v1/login.html?wechatid={0}&pkey={1}\">CLICK HERE</a>'
|
||||
|
||||
#Localized
|
||||
#Status
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package love.sola.netsupport.wechat;
|
||||
|
||||
import love.sola.netsupport.util.AESUtil;
|
||||
import love.sola.netsupport.util.RSAUtil;
|
||||
import org.junit.Test;
|
||||
import org.mindrot.jbcrypt.BCrypt;
|
||||
|
||||
@@ -19,9 +19,9 @@ public class TestEncrypt {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAES() {
|
||||
assert "Hello World".equals(AESUtil.decrypt(AESUtil.encrypt("Hello World")));
|
||||
assert "Encrypt".equals(AESUtil.decrypt(AESUtil.encrypt("Encrypt")));
|
||||
public void testRSA() {
|
||||
assert "Hello World".equals(RSAUtil.decrypt(RSAUtil.encrypt("Hello World")));
|
||||
assert "Encrypt".equals(RSAUtil.decrypt(RSAUtil.encrypt("Encrypt")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user