use RSA to encrypt login

This commit is contained in:
Sola
2015-12-13 01:54:11 +08:00
parent abb8891152
commit 0869a5ca7f
15 changed files with 183 additions and 71 deletions

View File

@@ -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>

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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 {
}

View File

@@ -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);
}
}
}

View File

@@ -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";

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}

View 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;
}
}

View File

@@ -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();
}
}

View File

@@ -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

View File

@@ -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")));
}
}