oauth2 v2 update

This commit is contained in:
Sola
2016-03-27 03:12:58 +08:00
parent 910bdca8a8
commit 850e45a2d8
48 changed files with 799 additions and 422 deletions

1
.gitignore vendored
View File

@@ -9,5 +9,4 @@ out/
.DS_Store
.classpath
/target
/src/main/webapp/META-INF/context.xml
.project

316
pom.xml
View File

@@ -1,162 +1,168 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<name>WechatTicketSystem</name>
<groupId>love.sola.netsupport</groupId>
<artifactId>WechatTicketSystem</artifactId>
<version>1.4-SNAPSHOT</version>
<packaging>war</packaging>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<name>WechatTicketSystem</name>
<groupId>love.sola.netsupport</groupId>
<artifactId>WechatTicketSystem</artifactId>
<version>1.4-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<source>1.8</source>
<target>1.8</target>
</properties>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<source>1.8</source>
<target>1.8</target>
</properties>
<scm>
<connection>scm:svn:http://127.0.0.1/dummy</connection>
<developerConnection>scm:svn:https://127.0.0.1/dummy</developerConnection>
<tag>HEAD</tag>
<url>http://127.0.0.1/dummy</url>
</scm>
<scm>
<connection>scm:svn:http://127.0.0.1/dummy</connection>
<developerConnection>scm:svn:https://127.0.0.1/dummy</developerConnection>
<tag>HEAD</tag>
<url>http://127.0.0.1/dummy</url>
</scm>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>1.4</version>
<configuration>
<format>{0,number,0000}</format>
<items>
<item>buildNumber0</item>
</items>
<doCheck>false</doCheck>
<doUpdate>false</doUpdate>
<revisionOnScmFailure>unknown</revisionOnScmFailure>
</configuration>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<finalName>${project.artifactId}##${buildNumber}</finalName>
</build>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>1.4</version>
<configuration>
<format>{0,number,0000}</format>
<items>
<item>buildNumber0</item>
</items>
<doCheck>false</doCheck>
<doUpdate>false</doUpdate>
<revisionOnScmFailure>unknown</revisionOnScmFailure>
</configuration>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<finalName>${project.artifactId}##${buildNumber}</finalName>
</build>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.6</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0-rc2</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.3</version>
</dependency>
<dependency>
<groupId>me.chanjar</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.0.3.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.0.3.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>5.0.3.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<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>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.16</version>
</dependency>
</dependencies>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.6</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0-rc2</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.3</version>
</dependency>
<dependency>
<groupId>me.chanjar</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.0.3.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.0.3.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>5.0.3.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<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>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.16</version>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.10</version>
</dependency>
</dependencies>
</project>

View File

@@ -1,8 +1,8 @@
package love.sola.netsupport.api;
import love.sola.netsupport.enums.Access;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.wechat.Command;
import me.chanjar.weixin.common.session.WxSession;
import javax.servlet.http.HttpServletRequest;

View File

@@ -1,15 +1,15 @@
package love.sola.netsupport.api;
import com.google.common.reflect.ClassPath;
import com.google.gson.Gson;
import love.sola.netsupport.enums.Access;
import love.sola.netsupport.enums.Attribute;
import love.sola.netsupport.pojo.Operator;
import love.sola.netsupport.pojo.User;
import love.sola.netsupport.session.WechatSession;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.sql.SQLCore;
import love.sola.netsupport.wechat.WechatSession;
import me.chanjar.weixin.common.session.WxSession;
import org.hibernate.HibernateException;
import org.reflections.Reflections;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
@@ -35,21 +35,20 @@ public class APIRouter extends HttpServlet {
protected static Gson gson = SQLCore.gson;
private Map<String, API> nodes = new HashMap<>();
public APIRouter() {
@Override
public void init() throws ServletException {
super.init();
try {
ClassPath path = ClassPath.from(getClass().getClassLoader());
Set<ClassPath.ClassInfo> classes = path.getTopLevelClassesRecursive(getClass().getPackage().getName());
for (ClassPath.ClassInfo info : classes) {
Class<?> clz = info.load();
if (!API.class.equals(clz) && API.class.isAssignableFrom(clz)) {
try {
System.out.print("Loading API: " + clz.getName());
API obj = (API) clz.newInstance();
System.out.println("Registered API: " + obj);
nodes.put(obj.url, obj);
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
Reflections reflections = new Reflections(getClass().getPackage().getName());
Set<Class<? extends API>> set = reflections.getSubTypesOf(API.class);
for (Class<? extends API> clz : set) {
try {
System.out.println("Loading API: " + clz.getName());
API obj = clz.newInstance();
System.out.println("Registered API: " + obj);
nodes.put(obj.url, obj);
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
} catch (Exception e) {
@@ -66,7 +65,7 @@ public class APIRouter extends HttpServlet {
resp.addHeader("Access-Control-Allow-Origin", "*");
Object obj = null;
try {
API api = nodes.get(req.getRequestURI());
API api = nodes.get(req.getPathInfo());
if (api == null) {
resp.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
@@ -82,14 +81,14 @@ public class APIRouter extends HttpServlet {
return;
}
if (api.access == Access.USER) {
User u = (User) session.getAttribute(Attribute.USER);
User u = session.getAttribute(Attribute.USER);
if (u == null) {
obj = Error.UNAUTHORIZED;
return;
}
}
if (api.access < Access.USER) {
Operator op = (Operator) session.getAttribute(Attribute.OPERATOR);
Operator op = session.getAttribute(Attribute.OPERATOR);
if (op == null) {
obj = Error.UNAUTHORIZED;
return;
@@ -121,7 +120,7 @@ public class APIRouter extends HttpServlet {
private static WxSession getSession(HttpServletRequest req) {
String t = req.getParameter("token");
if (t == null || t.isEmpty()) return null;
return WechatSession.get(t, false);
return WechatSession.get(t);
}
}

View File

@@ -2,7 +2,7 @@ package love.sola.netsupport.api;
import love.sola.netsupport.enums.Access;
import love.sola.netsupport.enums.Attribute;
import me.chanjar.weixin.common.session.WxSession;
import love.sola.netsupport.session.WxSession;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
@@ -17,7 +17,7 @@ import java.util.Map;
public class CheckSession extends API {
public CheckSession() {
url = "/api/checksession";
url = "/checksession";
access = Access.GUEST;
authorize = null;
}

View File

@@ -5,15 +5,14 @@ import love.sola.netsupport.enums.Access;
import love.sola.netsupport.enums.Attribute;
import love.sola.netsupport.pojo.Operator;
import love.sola.netsupport.pojo.User;
import love.sola.netsupport.session.WechatSession;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.sql.SQLCore;
import love.sola.netsupport.sql.TableOperator;
import love.sola.netsupport.sql.TableUser;
import love.sola.netsupport.util.Crypto;
import love.sola.netsupport.util.ParseUtil;
import love.sola.netsupport.util.RSAUtil;
import love.sola.netsupport.wechat.Command;
import love.sola.netsupport.wechat.WechatSession;
import me.chanjar.weixin.common.session.WxSession;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
@@ -45,8 +44,7 @@ public class Login extends HttpServlet {
response.addHeader("Content-type", "application/json;charset=utf-8");
response.addHeader("Access-Control-Allow-Origin", "*");
PrintWriter out = response.getWriter();
String json = gson.toJson(login(request));
out.println(ParseUtil.parseJsonP(request, json));
out.println(gson.toJson(login(request)));
out.close();
}
@@ -65,8 +63,7 @@ public class Login extends HttpServlet {
return Error.WRONG_PASSWORD;
}
String sid = WechatSession.genId();
WxSession session = WechatSession.get(sid, true);
WxSession session = WechatSession.create();
if (bypass) {
session.setAttribute(Attribute.AUTHORIZED, Command.fromId(Integer.parseInt(request.getParameter("bypass"))));
} else {
@@ -84,7 +81,7 @@ public class Login extends HttpServlet {
if (request.getParameter("bypasswechat") != null) {
session.setAttribute(Attribute.WECHAT, request.getParameter("bypasswechat"));
}
return sid;
return session.getId();
} catch (Exception e) {
e.printStackTrace();
return Error.INTERNAL_ERROR;

View File

@@ -4,9 +4,9 @@ import love.sola.netsupport.api.API;
import love.sola.netsupport.api.Error;
import love.sola.netsupport.enums.Access;
import love.sola.netsupport.pojo.User;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.sql.TableUser;
import love.sola.netsupport.wechat.Command;
import me.chanjar.weixin.common.session.WxSession;
import javax.servlet.http.HttpServletRequest;
@@ -19,7 +19,7 @@ import javax.servlet.http.HttpServletRequest;
public class GetUser extends API {
public GetUser() {
url = "/api/admin/getuser";
url = "/admin/getuser";
access = Access.LEADER;
authorize = Command.LOGIN;
}

View File

@@ -9,10 +9,10 @@ import love.sola.netsupport.enums.Status;
import love.sola.netsupport.pojo.Operator;
import love.sola.netsupport.pojo.Ticket;
import love.sola.netsupport.pojo.User;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.sql.SQLCore;
import love.sola.netsupport.util.Checker;
import love.sola.netsupport.wechat.Command;
import me.chanjar.weixin.common.session.WxSession;
import org.hibernate.Session;
import javax.servlet.http.HttpServletRequest;
@@ -26,7 +26,7 @@ import javax.servlet.http.HttpServletRequest;
public class TicketPush extends API {
public TicketPush() {
url = "/api/admin/ticketpush";
url = "/admin/ticketpush";
access = Access.LEADER;
authorize = Command.LOGIN;
}
@@ -41,7 +41,7 @@ public class TicketPush extends API {
if (desc.length() > Settings.MAX_DESC_LENGTH) {
return Error.LENGTH_LIMIT_EXCEEDED;
}
Operator op = (Operator) session.getAttribute(Attribute.OPERATOR);
Operator op = session.getAttribute(Attribute.OPERATOR);
try (Session s = SQLCore.sf.openSession()) {
s.beginTransaction();
User u = s.get(User.class, Long.parseLong(uid));

View File

@@ -2,13 +2,12 @@ package love.sola.netsupport.api.root;
import love.sola.netsupport.api.API;
import love.sola.netsupport.enums.Access;
import love.sola.netsupport.session.WechatSession;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.wechat.Command;
import love.sola.netsupport.wechat.WechatSession;
import me.chanjar.weixin.common.session.InternalSession;
import me.chanjar.weixin.common.session.WxSession;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.Set;
/**
* ***********************************************
@@ -19,7 +18,7 @@ import java.util.Enumeration;
public class DashBoard extends API {
public DashBoard() {
url = "/api/root/dashboard";
url = "/root/dashboard";
access = Access.ROOT;
authorize = Command.LOGIN;
}
@@ -27,13 +26,11 @@ public class DashBoard extends API {
@Override
protected Object process(HttpServletRequest req, WxSession session) throws Exception {
StringBuilder sb = new StringBuilder();
for (InternalSession s : WechatSession.list()) {
sb.append("=====").append(s.getIdInternal()).append("=====\n");
WxSession ws = s.getSession();
Enumeration<String> e = ws.getAttributeNames();
while (e.hasMoreElements()) {
String key = e.nextElement();
sb.append(key).append(": ").append(ws.getAttribute(key)).append("\n");
for (love.sola.netsupport.session.WxSession ws : WechatSession.list()) {
sb.append("=====").append(ws.getId()).append("=====\n");
Set<String> e = ws.getAttributeNames();
for (String key : e) {
sb.append(key).append(": ").append(ws.getAttribute(key).toString()).append("\n");
}
}
return sb.toString();

View File

@@ -3,9 +3,9 @@ package love.sola.netsupport.api.root;
import love.sola.netsupport.api.API;
import love.sola.netsupport.api.Error;
import love.sola.netsupport.enums.Access;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.sql.TableUser;
import love.sola.netsupport.wechat.Command;
import me.chanjar.weixin.common.session.WxSession;
import javax.servlet.http.HttpServletRequest;
@@ -18,7 +18,7 @@ import javax.servlet.http.HttpServletRequest;
public class FlushCache extends API {
public FlushCache() {
url = "/api/root/flushcache";
url = "/root/flushcache";
access = Access.ROOT;
authorize = Command.LOGIN;
}

View File

@@ -4,10 +4,10 @@ import love.sola.netsupport.api.API;
import love.sola.netsupport.api.Error;
import love.sola.netsupport.enums.Access;
import love.sola.netsupport.pojo.Operator;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.sql.SQLCore;
import love.sola.netsupport.util.Crypto;
import love.sola.netsupport.wechat.Command;
import me.chanjar.weixin.common.session.WxSession;
import org.hibernate.Session;
import javax.servlet.http.HttpServletRequest;
@@ -21,7 +21,7 @@ import javax.servlet.http.HttpServletRequest;
public class SetPassword extends API {
public SetPassword() {
url = "/api/root/setpass";
url = "/root/setpass";
access = Access.ROOT;
authorize = Command.LOGIN;
}

View File

@@ -3,10 +3,10 @@ package love.sola.netsupport.api.stuff;
import love.sola.netsupport.api.API;
import love.sola.netsupport.enums.Access;
import love.sola.netsupport.pojo.Ticket;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.sql.SQLCore;
import love.sola.netsupport.sql.TableTicket;
import love.sola.netsupport.wechat.Command;
import me.chanjar.weixin.common.session.WxSession;
import org.apache.commons.lang3.time.DateUtils;
import org.hibernate.Session;
import org.hibernate.envers.AuditReader;
@@ -28,7 +28,7 @@ public class TicketLog extends API {
public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
public TicketLog() {
url = "/api/admin/ticketlog";
url = "/admin/ticketlog";
access = Access.MEMBER;
authorize = Command.LOGIN;
}

View File

@@ -4,9 +4,9 @@ import love.sola.netsupport.api.API;
import love.sola.netsupport.enums.Access;
import love.sola.netsupport.enums.Attribute;
import love.sola.netsupport.pojo.Operator;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.sql.TableTicket;
import love.sola.netsupport.wechat.Command;
import me.chanjar.weixin.common.session.WxSession;
import javax.servlet.http.HttpServletRequest;
@@ -19,14 +19,14 @@ import javax.servlet.http.HttpServletRequest;
public class TicketLookup extends API {
public TicketLookup() {
url = "/api/admin/ticketlookup";
url = "/admin/ticketlookup";
access = Access.MEMBER;
authorize = Command.LOGIN;
}
@Override
protected Object process(HttpServletRequest req, WxSession session) throws Exception {
Operator op = (Operator) session.getAttribute(Attribute.OPERATOR);
Operator op = session.getAttribute(Attribute.OPERATOR);
int block;
if (req.getParameter("block") != null) {
block = Integer.parseInt(req.getParameter("block"));

View File

@@ -3,9 +3,9 @@ package love.sola.netsupport.api.stuff;
import love.sola.netsupport.api.API;
import love.sola.netsupport.api.Error;
import love.sola.netsupport.enums.Access;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.sql.TableTicket;
import love.sola.netsupport.wechat.Command;
import me.chanjar.weixin.common.session.WxSession;
import javax.servlet.http.HttpServletRequest;
@@ -18,7 +18,7 @@ import javax.servlet.http.HttpServletRequest;
public class TicketTrack extends API {
public TicketTrack() {
url = "/api/admin/tickettrack";
url = "/admin/tickettrack";
access = Access.MEMBER;
authorize = Command.LOGIN;
}

View File

@@ -6,10 +6,10 @@ import love.sola.netsupport.enums.Access;
import love.sola.netsupport.enums.Attribute;
import love.sola.netsupport.pojo.Operator;
import love.sola.netsupport.pojo.Ticket;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.sql.SQLCore;
import love.sola.netsupport.util.Checker;
import love.sola.netsupport.wechat.Command;
import me.chanjar.weixin.common.session.WxSession;
import org.hibernate.Session;
import javax.servlet.http.HttpServletRequest;
@@ -24,7 +24,7 @@ import java.util.Date;
public class TicketUpdate extends API {
public TicketUpdate() {
url = "/api/admin/ticketupdate";
url = "/admin/ticketupdate";
access = Access.MEMBER;
authorize = Command.LOGIN;
}
@@ -36,7 +36,7 @@ public class TicketUpdate extends API {
String status = req.getParameter("status");
if (Checker.hasNull(ticket, remark, status)) return Error.PARAMETER_REQUIRED;
try (Session s = SQLCore.sf.openSession()) {
Operator op = (Operator) session.getAttribute(Attribute.OPERATOR);
Operator op = session.getAttribute(Attribute.OPERATOR);
Ticket t = s.get(Ticket.class, Integer.parseInt(ticket));
if (t == null) {
return Error.TICKET_NOT_FOUND;

View File

@@ -6,9 +6,9 @@ import love.sola.netsupport.enums.Access;
import love.sola.netsupport.enums.Attribute;
import love.sola.netsupport.enums.ISP;
import love.sola.netsupport.pojo.User;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.sql.TableUser;
import love.sola.netsupport.wechat.Command;
import me.chanjar.weixin.common.session.WxSession;
import org.hibernate.exception.ConstraintViolationException;
import javax.servlet.http.HttpServletRequest;
@@ -24,14 +24,14 @@ import static love.sola.netsupport.util.Checker.*;
public class ProfileModify extends API {
public ProfileModify() {
url = "/api/profilemodify";
url = "/profilemodify";
access = Access.USER;
authorize = Command.PROFILE;
}
@Override
protected Object process(HttpServletRequest req, WxSession session) throws Exception {
User u = (User) session.getAttribute(Attribute.USER);
User u = session.getAttribute(Attribute.USER);
ISP isp = checkISP(req.getParameter("isp"));
String netAccount = checkNetAccount(req.getParameter("username"), isp);
int block = checkBlock(req.getParameter("block"));

View File

@@ -6,12 +6,12 @@ import love.sola.netsupport.enums.Access;
import love.sola.netsupport.enums.Attribute;
import love.sola.netsupport.enums.ISP;
import love.sola.netsupport.pojo.User;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.sql.SQLCore;
import love.sola.netsupport.sql.TableUser;
import love.sola.netsupport.wechat.Command;
import love.sola.netsupport.wechat.WxMpServlet;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.session.WxSession;
import me.chanjar.weixin.mp.bean.WxMpCustomMessage;
import org.hibernate.exception.ConstraintViolationException;
@@ -32,14 +32,14 @@ import static love.sola.netsupport.util.Checker.*;
public class Register extends API {
public Register() {
url = "/api/register";
url = "/register";
access = Access.GUEST;
authorize = Command.REGISTER;
}
@Override
protected Object process(HttpServletRequest req, WxSession session) throws Exception {
String wechat = (String) session.getAttribute(Attribute.WECHAT);
String wechat = session.getAttribute(Attribute.WECHAT);
if (wechat == null) {
return Error.UNAUTHORIZED;
}

View File

@@ -5,9 +5,9 @@ import love.sola.netsupport.enums.Access;
import love.sola.netsupport.enums.Attribute;
import love.sola.netsupport.pojo.Ticket;
import love.sola.netsupport.pojo.User;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.sql.SQLCore;
import love.sola.netsupport.wechat.Command;
import me.chanjar.weixin.common.session.WxSession;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
@@ -24,7 +24,7 @@ import javax.servlet.http.HttpServletRequest;
public class TicketQuery extends API {
public TicketQuery() {
url = "/api/ticketquery";
url = "/ticketquery";
access = Access.USER;
authorize = Command.QUERY;
}
@@ -32,7 +32,7 @@ public class TicketQuery extends API {
@Override
protected Object process(HttpServletRequest req, WxSession session) throws Exception {
try (Session s = SQLCore.sf.openSession()) {
User u = (User) session.getAttribute(Attribute.USER);
User u = session.getAttribute(Attribute.USER);
Criteria c = s.createCriteria(Ticket.class);
int first = req.getParameter("offset") == null ? 0 : Integer.parseInt(req.getParameter("offset"));
int limit = req.getParameter("limit") == null ? 5 : Integer.parseInt(req.getParameter("limit"));

View File

@@ -7,10 +7,10 @@ import love.sola.netsupport.enums.Access;
import love.sola.netsupport.enums.Attribute;
import love.sola.netsupport.pojo.Ticket;
import love.sola.netsupport.pojo.User;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.sql.SQLCore;
import love.sola.netsupport.sql.TableTicket;
import love.sola.netsupport.wechat.Command;
import me.chanjar.weixin.common.session.WxSession;
import org.hibernate.Session;
import javax.servlet.http.HttpServletRequest;
@@ -24,7 +24,7 @@ import javax.servlet.http.HttpServletRequest;
public class TicketSubmit extends API {
public TicketSubmit() {
url = "/api/ticketsubmit";
url = "/ticketsubmit";
access = Access.USER;
authorize = Command.SUBMIT;
}
@@ -40,7 +40,7 @@ public class TicketSubmit extends API {
}
try (Session s = SQLCore.sf.openSession()) {
User u = (User) session.getAttribute(Attribute.USER);
User u = session.getAttribute(Attribute.USER);
if (TableTicket.hasOpen(u)) {
session.invalidate();
return Error.ALREADY_SUBMITTED;

View File

@@ -1,12 +1,11 @@
package love.sola.netsupport.auth;
import love.sola.netsupport.session.WechatSession;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.util.Checker;
import love.sola.netsupport.wechat.WechatSession;
import love.sola.netsupport.wechat.WxMpServlet;
import me.chanjar.weixin.common.session.WxSession;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
@@ -15,6 +14,8 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* ***********************************************
@@ -22,9 +23,20 @@ import java.io.IOException;
* Don't modify this source without my agreement
* ***********************************************
*/
@WebServlet(name = "OAuth2", urlPatterns = "/oauth2/callback", loadOnStartup = 21)
@WebServlet(name = "OAuth2", urlPatterns = "/oauth2/callback", loadOnStartup = 21, asyncSupported = true)
public class OAuth2 extends HttpServlet {
private static Map<String, OAuth2Handler> oAuth2HandlerMap = new HashMap<>();
/**
* for {@link love.sola.netsupport.wechat.WxMpServlet#registerCommands}
* @param state the state key from open platform callback.
* @param handler handler
*/
public static void registerOAuth2Handler(String state, OAuth2Handler handler) {
oAuth2HandlerMap.put(state, handler);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
AsyncContext acxt = req.startAsync();
@@ -34,13 +46,19 @@ public class OAuth2 extends HttpServlet {
resp.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
OAuth2Handler handler = oAuth2HandlerMap.get(state);
if (handler == null) {
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
return;
}
acxt.start(() -> {
try {
WxMpService wxMpService = WxMpServlet.instance.wxMpService;
WxMpOAuth2AccessToken token = wxMpService.oauth2getAccessToken(code);
WxMpUser wxUser = wxMpService.oauth2getUserInfo(token, "zh_CN");
String sid = WechatSession.genId();
WxSession session = WechatSession.get(sid, true);
String wechat = token.getOpenId();
WxSession session = WechatSession.create();
handler.onOAuth2(acxt, (HttpServletResponse) acxt.getResponse(), wechat, session);
acxt.complete();
} catch (Exception e) {
e.printStackTrace();
}

View File

@@ -0,0 +1,18 @@
package love.sola.netsupport.auth;
import love.sola.netsupport.session.WxSession;
import javax.servlet.AsyncContext;
import javax.servlet.http.HttpServletResponse;
/**
* ***********************************************
* Created by Sola on 2016/3/26.
* Don't modify this source without my agreement
* ***********************************************
*/
public interface OAuth2Handler {
void onOAuth2(AsyncContext acxt, HttpServletResponse resp, String user, WxSession session);
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package love.sola.netsupport.session;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
/**
* @author Sola
*/
@EqualsAndHashCode(of = "id")
public final class MapSession implements WxSession, Serializable {
@Getter
private final String id;
private Map<String, Object> sessionAttrs = new HashMap<String, Object>();
@Getter
private long creationTime = System.currentTimeMillis();
@Getter
@Setter
private long lastAccessedTime = creationTime;
@Getter
private boolean invalidated = false;
/**
* Creates a new instance with a secure randomly generated identifier.
*/
public MapSession() {
this(UUID.randomUUID().toString());
}
/**
* Creates a new instance with the specified id. This is preferred to the
* default constructor when the id is known to prevent unnecessary consumption on
* entropy which can be slow.
*
* @param id the identifier to use
*/
public MapSession(String id) {
this.id = id;
}
@SuppressWarnings("unchecked")
public <T> T getAttribute(String attributeName) {
return (T) sessionAttrs.get(attributeName);
}
public Set<String> getAttributeNames() {
return sessionAttrs.keySet();
}
public void setAttribute(String attributeName, Object attributeValue) {
if (attributeValue == null) {
removeAttribute(attributeName);
} else {
sessionAttrs.put(attributeName, attributeValue);
}
}
public void removeAttribute(String attributeName) {
sessionAttrs.remove(attributeName);
}
public void invalidate() {
invalidated = true;
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package love.sola.netsupport.session;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import love.sola.netsupport.config.Settings;
import org.apache.commons.lang3.Validate;
import javax.annotation.Nonnull;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @author Sola
*/
public class MapSessionRepository {
private final LoadingCache<String, MapSession> sessions;
public MapSessionRepository() {
this(CacheBuilder.newBuilder()
.concurrencyLevel(4)
.maximumSize(65535)
.expireAfterAccess(Settings.I.User_Session_Max_Inactive, TimeUnit.SECONDS)
.build(new CacheLoader<String, MapSession>() {
@Override
public MapSession load(@Nonnull String key) throws Exception {
return new MapSession(key);
}
}
)
);
}
public MapSessionRepository(LoadingCache<String, MapSession> sessions) {
Validate.notNull(sessions);
this.sessions = sessions;
}
public void save(MapSession session) {
sessions.put(session.getId(), session);
}
public MapSession getSession(String id) {
MapSession saved = sessions.getIfPresent(id);
if (saved == null) {
return null;
}
if (saved.isInvalidated()) {
delete(saved.getId());
return null;
}
return saved;
}
public void delete(String id) {
sessions.invalidate(id);
}
public MapSession createSession() {
MapSession session = new MapSession();
save(session);
return session;
}
public Map<String, MapSession> asMap() {
return sessions.asMap();
}
}

View File

@@ -0,0 +1,32 @@
package love.sola.netsupport.session;
import java.util.Collection;
/**
* ***********************************************
* Created by Sola on 2015/12/14.
* Don't modify this source without my agreement
* ***********************************************
*/
public class WechatSession {
private static MapSessionRepository repository;
static {
repository = new MapSessionRepository();
}
public static WxSession get(String id) {
return repository.getSession(id);
}
public static WxSession create() {
return repository.createSession();
}
public static Collection<? extends WxSession> list() {
return repository.asMap().values();
}
}

View File

@@ -0,0 +1,22 @@
package love.sola.netsupport.session;
import java.util.Set;
/**
* @author Sola
*/
public interface WxSession {
String getId();
<T> T getAttribute(String name);
Set<String> getAttributeNames();
void setAttribute(String name, Object value);
void removeAttribute(String name);
void invalidate();
}

View File

@@ -5,6 +5,7 @@ import com.google.gson.annotations.Expose;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import love.sola.netsupport.enums.ISP;
import love.sola.netsupport.wechat.Command;
import org.hibernate.Hibernate;
@@ -18,6 +19,7 @@ import org.hibernate.proxy.HibernateProxy;
import org.hibernate.service.ServiceRegistry;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.io.IOException;
import java.util.Date;
@@ -30,7 +32,10 @@ import java.util.Date;
*/
public class SQLCore {
public static InitialContext ic;
public static DataSource ds;
public static SessionFactory sf;
public static ServiceRegistry sr;
public static Gson gson = new GsonBuilder()
.addSerializationExclusionStrategy(new ExclusionStrategy() {
@Override
@@ -64,12 +69,10 @@ public class SQLCore {
.registerTypeAdapter(Command.class, (JsonSerializer<Command>) (src, typeOfSrc, context) -> new JsonPrimitive(src.id))
.registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY)
.create();
public static SessionFactory sf;
public static ServiceRegistry sr;
static {
try {
InitialContext ic = new InitialContext();
ic = new InitialContext();
ds = (DataSource) ic.lookup("java:comp/env/jdbc/netsupport");
ds.setLoginTimeout(3);
@@ -83,6 +86,16 @@ public class SQLCore {
}
}
public static void destroy() {
try {
SQLCore.sf.close();
((ComboPooledDataSource) SQLCore.ds).close();
SQLCore.ic.close();
} catch (NamingException e) {
e.printStackTrace();
}
}
public static AuditReader getAuditReader(Session session) {
return AuditReaderFactory.get(session);
}

View File

@@ -72,7 +72,7 @@ public class TableUser extends SQLCore {
private static LoadingCache<String, User> cache = CacheBuilder.newBuilder()
.concurrencyLevel(4)
.maximumSize(4096)
.expireAfterWrite(Settings.I.User_Wechat_Cache_Expire_Time, TimeUnit.SECONDS)
.expireAfterAccess(Settings.I.User_Wechat_Cache_Expire_Time, TimeUnit.SECONDS)
.build(new ValueLoader());
private static class ValueLoader extends CacheLoader<String, User> {

View File

@@ -1,13 +1,7 @@
package love.sola.netsupport.util;
import love.sola.netsupport.enums.Attribute;
import love.sola.netsupport.enums.Block;
import love.sola.netsupport.enums.ISP;
import love.sola.netsupport.wechat.Command;
import love.sola.netsupport.wechat.WechatSession;
import me.chanjar.weixin.common.session.WxSession;
import javax.servlet.http.HttpServletRequest;
/**
* ***********************************************
@@ -25,13 +19,6 @@ public class Checker {
return false;
}
public static WxSession isAuthorized(HttpServletRequest r, Command c) {
String t = r.getParameter("token");
if (t == null || t.isEmpty()) return null;
WxSession s = WechatSession.get(t, false);
return s == null ? null : s.getAttribute(Attribute.AUTHORIZED) == c ? s : null;
}
public static long checkStudentId(String studentId) {
if (studentId == null) return -1;
if (studentId.matches(STUDENT_ID_REGEX)) {

View File

@@ -3,7 +3,6 @@ package love.sola.netsupport.util;
import love.sola.netsupport.enums.Status;
import love.sola.netsupport.pojo.Ticket;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import static love.sola.netsupport.config.Lang.lang;
@@ -30,11 +29,4 @@ public class ParseUtil {
return sb.toString();
}
public static String parseJsonP(HttpServletRequest request, String json) {
String jsonp = request.getParameter("jsonp");
if (jsonp == null || jsonp.isEmpty())
return json;
else
return jsonp.replace("{0}", json);
}
}

View File

@@ -1,5 +1,7 @@
package love.sola.netsupport.util;
import com.google.common.net.UrlEscapers;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@@ -13,15 +15,106 @@ import static love.sola.netsupport.config.Lang.lang;
*/
public class Redirect {
public static final String REDIRECT_PAGE = lang("Result_Page");
private static final String REDIRECT_PAGE = lang("Result_Page");
private static final int SUCCESS = 1;
private static final int ERROR = 0;
private static final int WARNING = -1;
private static final int NON_WECHAT = 88;
public static RedirectBuilder success() {
return new RedirectBuilder(SUCCESS);
}
public static RedirectBuilder error() {
return new RedirectBuilder(ERROR);
}
public static class RedirectBuilder {
private StringBuilder sb;
RedirectBuilder(int type) {
sb = new StringBuilder(REDIRECT_PAGE).append("?");
type(type);
}
private RedirectBuilder type(int type) {
sb.append("type=").append(type).append("&");
return this;
}
public RedirectBuilder msg(String msg) {
sb.append("msg=").append(i18nThenEscape(msg)).append("&");
return this;
}
public RedirectBuilder title(String title) {
sb.append("title=").append(i18nThenEscape(title)).append("&");
return this;
}
public RedirectBuilder noButton() {
sb.append("btn=").append("hide").append("&");
return this;
}
public RedirectBuilder button(String text) {
sb.append("btn=").append(i18nThenEscape(text)).append("&");
return this;
}
public RedirectBuilder icon(WeUIIcon icon) {
sb.append("icon=").append(icon.toString()).append("&");
return this;
}
public RedirectBuilder to(String url) {
sb.append("redirect=").append(i18nThenEscape(url)).append("&");
return this;
}
public void go(HttpServletResponse resp) throws IOException {
resp.sendRedirect(sb.toString());
}
public String toString() {
return sb.toString();
}
private static String i18nThenEscape(String str) {
return UrlEscapers.urlFragmentEscaper().escape(lang(str));
}
}
public enum WeUIIcon {
SUCCESS("weui_icon_success"),
SUCCESS_CIRCLE("weui_icon_success_circle"),
SUCCESS_NO_CIRCLE("weui_icon_success_no_circle"),
SUCCESS_SAFE("weui_icon_safe_success"),
INFO("weui_icon_info"),
INFO_CIRCLE("weui_icon_info_circle"),
WAITING("weui_icon_waiting"),
WAITING_CIRCLE("weui_icon_waiting_circle"),
CIRCLE("weui_icon_circle"),
WARN("weui_icon_warn"),
WARN_SAFE("weui_icon_safe_warn"),
DOWNLOAD("weui_icon_download"),
CANCEL("weui_icon_cancel"),
;
private String value;
WeUIIcon(String value) {
this.value = value;
}
@Override
public String toString() {
return value;
}
public static void message(HttpServletResponse response, int type, String message) throws IOException {
response.sendRedirect(
response.encodeRedirectURL(REDIRECT_PAGE +
"?msg=" + message +
"&type=" + type
)
);
}
}

View File

@@ -1,43 +0,0 @@
package love.sola.netsupport.wechat;
import love.sola.netsupport.config.Settings;
import me.chanjar.weixin.common.session.*;
import java.util.UUID;
/**
* ***********************************************
* Created by Sola on 2015/12/14.
* Don't modify this source without my agreement
* ***********************************************
*/
public class WechatSession {
private static StandardSessionManager manager;
static{
manager = new StandardSessionManager();
manager.setMaxInactiveInterval(Settings.I.User_Session_Max_Inactive);
}
public static WxSession get(String id, boolean create) {
WxSession session = manager.getSession(id, create);
if (session != null) {
((StandardSessionFacade) session).getInternalSession().endAccess();
}
return session;
}
public static WxSession get(String id) {
return get(id, true);
}
public static String genId() {
return UUID.randomUUID().toString();
}
public static InternalSession[] list() {
return manager.findSessions();
}
}

View File

@@ -1,6 +1,9 @@
package love.sola.netsupport.wechat;
import love.sola.netsupport.auth.OAuth2;
import love.sola.netsupport.auth.OAuth2Handler;
import love.sola.netsupport.config.Settings;
import love.sola.netsupport.sql.SQLCore;
import love.sola.netsupport.wechat.handler.RegisterHandler;
import love.sola.netsupport.wechat.handler.SubscribeHandler;
import love.sola.netsupport.wechat.matcher.CheckSpamMatcher;
@@ -86,6 +89,9 @@ public class WxMpServlet extends HttpServlet {
WxMpMessageHandler handler = c.handler.newInstance();
router.rule().async(false).msgType(WxConsts.XML_MSG_TEXT).rContent(c.regex).handler(handler).end();
router.rule().async(false).msgType(WxConsts.XML_MSG_EVENT).event(WxConsts.EVT_CLICK).eventKey(c.name()).handler(handler).end();
if (handler instanceof OAuth2Handler) {
OAuth2.registerOAuth2Handler(c.name(), (OAuth2Handler) handler);
}
}
}
@@ -153,4 +159,8 @@ public class WxMpServlet extends HttpServlet {
doPost(req, resp);
}
@Override
public void destroy() {
SQLCore.destroy();
}
}

View File

@@ -2,11 +2,11 @@ package love.sola.netsupport.wechat.handler;
import love.sola.netsupport.enums.Attribute;
import love.sola.netsupport.pojo.User;
import love.sola.netsupport.session.WechatSession;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.sql.TableUser;
import love.sola.netsupport.wechat.Command;
import love.sola.netsupport.wechat.WechatSession;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.session.WxSession;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpService;
@@ -29,13 +29,12 @@ public class ProfileHandler implements WxMpMessageHandler {
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {
User u = TableUser.getByWechat(wxMessage.getFromUserName());
String id = WechatSession.genId();
WxSession session = WechatSession.get(id, true);
WxSession session = WechatSession.create();
session.setAttribute(Attribute.AUTHORIZED, Command.PROFILE);
session.setAttribute(Attribute.WECHAT, wxMessage.getFromUserName());
session.setAttribute(Attribute.USER, u);
TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName());
out.content(format("Profile_Modify", format("User_Profile_Link", id, u.getName(), u.getIsp().id, u.getNetAccount(), u.getBlock(), u.getRoom(), u.getPhone())));
out.content(format("Profile_Modify", format("User_Profile_Link", session.getId(), u.getName(), u.getIsp().id, u.getNetAccount(), u.getBlock(), u.getRoom(), u.getPhone())));
return out.build();
}

View File

@@ -3,13 +3,13 @@ package love.sola.netsupport.wechat.handler;
import love.sola.netsupport.enums.Attribute;
import love.sola.netsupport.pojo.Ticket;
import love.sola.netsupport.pojo.User;
import love.sola.netsupport.session.WechatSession;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.sql.TableTicket;
import love.sola.netsupport.sql.TableUser;
import love.sola.netsupport.util.ParseUtil;
import love.sola.netsupport.wechat.Command;
import love.sola.netsupport.wechat.WechatSession;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.session.WxSession;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpService;
@@ -40,8 +40,7 @@ public class QueryHandler implements WxMpMessageHandler {
return WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName())
.content(lang("No_Ticket_Available")).build();
}
String id = WechatSession.genId();
WxSession session = WechatSession.get(id, true);
WxSession session = WechatSession.create();
session.setAttribute(Attribute.AUTHORIZED, Command.QUERY);
session.setAttribute(Attribute.WECHAT, wxMessage.getFromUserName());
session.setAttribute(Attribute.USER, u);
@@ -50,7 +49,7 @@ public class QueryHandler implements WxMpMessageHandler {
WxMpXmlOutNewsMessage.Item item = new WxMpXmlOutNewsMessage.Item();
item.setTitle(lang("Query_Title"));
item.setDescription(ParseUtil.parseTicket(t) + "\n" + lang("More_Details"));
item.setUrl(format("User_Query_Link", id));
item.setUrl(format("User_Query_Link", session.getId()));
out.addArticle(item);
return out.build();
}

View File

@@ -2,11 +2,11 @@ package love.sola.netsupport.wechat.handler;
import love.sola.netsupport.enums.Attribute;
import love.sola.netsupport.pojo.User;
import love.sola.netsupport.session.WechatSession;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.sql.TableUser;
import love.sola.netsupport.wechat.Command;
import love.sola.netsupport.wechat.WechatSession;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.session.WxSession;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpService;
@@ -32,17 +32,16 @@ public class RegisterHandler implements WxMpMessageHandler {
TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName());
String fromUser = wxMessage.getFromUserName();
User u = TableUser.getByWechat(fromUser);
String id = WechatSession.genId();
WxSession session = WechatSession.get(id, true);
WxSession session = WechatSession.create();
if (u != null) {
session.setAttribute(Attribute.AUTHORIZED, Command.PROFILE);
session.setAttribute(Attribute.WECHAT, fromUser);
session.setAttribute(Attribute.USER, u);
out.content(format("Already_Registered", format("User_Profile_Link", id, u.getName(), u.getIsp().id, u.getNetAccount(), u.getBlock(), u.getRoom(), u.getPhone())));
out.content(format("Already_Registered", format("User_Profile_Link", session.getId(), u.getName(), u.getIsp().id, u.getNetAccount(), u.getBlock(), u.getRoom(), u.getPhone())));
} else {
session.setAttribute(Attribute.AUTHORIZED, Command.REGISTER);
session.setAttribute(Attribute.WECHAT, fromUser);
out.content(format("User_Register", format("User_Register_Link", id)));
out.content(format("User_Register", format("User_Register_Link", session.getId())));
}
return out.build();
}

View File

@@ -2,12 +2,12 @@ package love.sola.netsupport.wechat.handler;
import love.sola.netsupport.enums.Attribute;
import love.sola.netsupport.pojo.User;
import love.sola.netsupport.session.WechatSession;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.sql.TableTicket;
import love.sola.netsupport.sql.TableUser;
import love.sola.netsupport.wechat.Command;
import love.sola.netsupport.wechat.WechatSession;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.session.WxSession;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpService;
@@ -36,8 +36,7 @@ public class SubmitHandler implements WxMpMessageHandler {
return WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName())
.content(lang("Already_Opening_Ticket")).build();
}
String id = WechatSession.genId();
WxSession session = WechatSession.get(id, true);
WxSession session = WechatSession.create();
session.setAttribute(Attribute.AUTHORIZED, Command.SUBMIT);
session.setAttribute(Attribute.WECHAT, wxMessage.getFromUserName());
session.setAttribute(Attribute.USER, u);
@@ -46,7 +45,7 @@ public class SubmitHandler implements WxMpMessageHandler {
WxMpXmlOutNewsMessage.Item item = new WxMpXmlOutNewsMessage.Item();
item.setTitle(lang("Submit_Title"));
item.setDescription(lang("Submit_Desc"));
item.setUrl(format("User_Submit_Link", id, u.getName(), u.getIsp().id, u.getRoom(), u.getBlock(), u.getPhone()));
item.setUrl(format("User_Submit_Link", session.getId(), u.getName(), u.getIsp().id, u.getRoom(), u.getBlock(), u.getPhone()));
out.addArticle(item);
return out.build();
}

View File

@@ -4,12 +4,12 @@ import love.sola.netsupport.api.user.Register;
import love.sola.netsupport.enums.Attribute;
import love.sola.netsupport.pojo.Operator;
import love.sola.netsupport.pojo.User;
import love.sola.netsupport.session.WechatSession;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.sql.TableOperator;
import love.sola.netsupport.sql.TableUser;
import love.sola.netsupport.wechat.Command;
import love.sola.netsupport.wechat.WechatSession;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.session.WxSession;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpService;
@@ -34,13 +34,12 @@ public class SubscribeHandler implements WxMpMessageHandler {
TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName());
String fromUser = wxMessage.getFromUserName();
User u = TableUser.getByWechat(fromUser);
String id = WechatSession.genId();
WxSession session = WechatSession.get(id, true);
WxSession session = WechatSession.create();
if (u != null) {
session.setAttribute(Attribute.AUTHORIZED, Command.PROFILE);
session.setAttribute(Attribute.WECHAT, fromUser);
session.setAttribute(Attribute.USER, u);
out.content(format("Event_Subscribe", format("Already_Registered", format("User_Profile_Link", id, u.getName(), u.getIsp().id, u.getNetAccount(), u.getBlock(), u.getRoom(), u.getPhone()))));
out.content(format("Event_Subscribe", format("Already_Registered", format("User_Profile_Link", session.getId(), u.getName(), u.getIsp().id, u.getNetAccount(), u.getBlock(), u.getRoom(), u.getPhone()))));
Operator op = TableOperator.get(fromUser);
if (op != null) {
@@ -51,7 +50,7 @@ public class SubscribeHandler implements WxMpMessageHandler {
} else {
session.setAttribute(Attribute.AUTHORIZED, Command.REGISTER);
session.setAttribute(Attribute.WECHAT, fromUser);
out.content(format("Event_Subscribe", format("User_Register", format("User_Register_Link", id))));
out.content(format("Event_Subscribe", format("User_Register", format("User_Register_Link", session.getId()))));
}
return out.build();
}

View File

@@ -1,13 +1,15 @@
package love.sola.netsupport.wechat.handler.admin;
import love.sola.netsupport.auth.OAuth2Handler;
import love.sola.netsupport.enums.Access;
import love.sola.netsupport.enums.Attribute;
import love.sola.netsupport.pojo.Operator;
import love.sola.netsupport.session.WechatSession;
import love.sola.netsupport.session.WxSession;
import love.sola.netsupport.sql.TableOperator;
import love.sola.netsupport.util.Redirect;
import love.sola.netsupport.wechat.Command;
import love.sola.netsupport.wechat.WechatSession;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.session.WxSession;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpService;
@@ -15,6 +17,8 @@ import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.outxmlbuilder.TextBuilder;
import javax.servlet.AsyncContext;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import static love.sola.netsupport.config.Lang.format;
@@ -26,7 +30,7 @@ import static love.sola.netsupport.config.Lang.lang;
* Don't modify this source without my agreement
* ***********************************************
*/
public class LoginHandler implements WxMpMessageHandler {
public class LoginHandler implements WxMpMessageHandler, OAuth2Handler {
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {
@@ -38,14 +42,12 @@ public class LoginHandler implements WxMpMessageHandler {
else if (operator.getAccess() >= Access.NO_LOGIN) {
out.content(lang("No_Login"));
} else {
String id = WechatSession.genId();
WxSession session = WechatSession.get(id, true);
WxSession session = WechatSession.create();
session.setAttribute(Attribute.AUTHORIZED, Command.LOGIN);
session.setAttribute(Attribute.WECHAT, wxMessage.getFromUserName());
session.setAttribute(Attribute.OPERATOR, operator);
out.content(format("Operator_Home_Page", id));
out.content(format("Home_Page_Msg", format("Operator_Home_Page", session.getId())));
}
} catch (Exception e) {
e.printStackTrace();
out.content(lang("Login_Error"));
@@ -53,4 +55,28 @@ public class LoginHandler implements WxMpMessageHandler {
return out.build();
}
@Override
public void onOAuth2(AsyncContext acxt, HttpServletResponse resp, String user, WxSession session) {
try {
Operator operator = TableOperator.get(user);
if (operator == null) {
Redirect.error().icon(Redirect.WeUIIcon.WARN_SAFE).noButton()
.title("Not_Operator").msg("Not_Operator_OAuth2").go(resp);
return;
}
if (operator.getAccess() >= Access.NO_LOGIN) {
Redirect.error().icon(Redirect.WeUIIcon.WAITING).noButton()
.title("Left_Operator_Title").msg("Left_Operator").go(resp);
return;
}
session.setAttribute(Attribute.AUTHORIZED, Command.LOGIN);
session.setAttribute(Attribute.WECHAT, user);
session.setAttribute(Attribute.OPERATOR, operator);
resp.sendRedirect(format("Operator_Home_Page", session.getId()));
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -43,15 +43,19 @@ Cancel_Failed: '取消失败。'
#Modify
Profile_Modify: '<a href="{0}">> 点此修改资料 <</a>'
#Login
Home_Page_Msg: '<a href="{0}">CLICK HERE</a>'
Not_Operator: '嘟嘟嘟……'
Not_Operator_OAuth2: '看起来你并不是我们网维大家族的一员,但我们随时都欢迎你的加入哦!'
No_Login: 'Permission Denied.'
Left_Operator_Title: '一路上有你'
Left_Operator: '网络维护科的茁壮成长离不开每一位成员的陪伴。一路上有你,感谢你对网络维护科的贡献!'
Internal_Error: '啊哦,登录失败了哦。'
#Operator_Info
Operator_Info: |
网维成员资料:
网维ID: {0,number,#}
姓名: {1}
岗位: {2,choice,0#'Administrator >ω<'|3#值班组长|6#正式成员|7#实习成员|}
岗位: {2,choice,0#'Administrator >ω<'|3#值班组长|6#正式成员|7#实习成员|9#'曾经的一员(TдT)'}
值班片区: {3,choice,0#'全图 >ω<'|1#岐头片区|2#北门片区|3#东门片区|4#香灰片区|5#凤翔片区}
值班日: {4,choice,0#'2月30日 >ω<'|1#周一|2#周二|3#周三|4#周四|5#周五|6#周六|7#周日}
@@ -62,7 +66,7 @@ User_Query_Link: 'http://topaz.sinaapp.com/nm/v2/user/list.html?token={0}'
User_Submit_Link: 'http://topaz.sinaapp.com/nm/v2/user/rrepair.html?token={0}&name={1}&isp={2}&room={3}&block={4}&phone={5,number,#}'
User_Profile_Link: 'http://topaz.sinaapp.com/nm/v2/user/modi.html?token={0}&name={1}&isp={2}&username={3}&block={4}&room={5}&phone={6,number,#}'
Result_Page: 'http://topaz.sinaapp.com/nm/v2/result.html'
Operator_Home_Page: '<a href="http://topaz.sinaapp.com/nm/v2/man/home.html?token={0}">CLICK HERE</a>'
Operator_Home_Page: 'http://topaz.sinaapp.com/nm/v2/man/home.html?token={0}'
Operator_Login_Page: 'http://topaz.sinaapp.com/nm/v2/man/login.html?pkey={0}'
#Localized

View File

@@ -34,9 +34,9 @@
"key": "OPERATOR_INFO"
},
{
"type": "click",
"type": "view",
"name": "后台登录",
"key": "LOGIN"
"url": "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxb7a8b799e494b053&redirect_uri=http%3a%2f%2fwcs.sola.love%2foauth2%2fcallback&response_type=code&scope=snsapi_base&state=LOGIN#wechat_redirect"
}
]
}

View File

@@ -0,0 +1,48 @@
<?xml version='1.0' encoding='utf-8'?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- The contents of this file will be loaded for each web application -->
<Context swallowOutput="false" antiResourceLocking="true">
<!-- Default set of monitored resources -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
<Resource auth="Container"
description="C3P0 database connection pool"
driverClass="com.mysql.jdbc.Driver"
maxPoolSize="10"
minPoolSize="2"
acquireIncrement="1"
maxIdleTime="3600"
idleConnectionTestPeriod="1800"
name="jdbc/netsupport"
user="root"
password=""
factory="org.apache.naming.factory.BeanFactory"
type="com.mchange.v2.c3p0.ComboPooledDataSource"
jdbcUrl="jdbc:mysql://localhost:3306/netsupport?autoReconnect=true&amp;characterEncoding=utf8" />
<!-- Uncomment this to enable Comet connection tacking (provides events
on session expiration as well as webapp lifecycle) -->
<!--
<Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
-->
</Context>

View File

@@ -1,34 +1,23 @@
package love.sola.netsupport.api;
import com.google.common.reflect.ClassPath;
import org.junit.Test;
import org.reflections.Reflections;
import java.io.IOException;
import java.util.Set;
/**
* ***********************************************
* Created by Sola on 2014/8/20.
* Created by Sola on 2016/3/26.
* Don't modify this source without my agreement
* ***********************************************
*/
public class ReflectionTest {
@Test
public void test() throws IOException, IllegalAccessException, InstantiationException {
int count = 0;
ClassPath path = ClassPath.from(getClass().getClassLoader());
Set<ClassPath.ClassInfo> classes = path.getTopLevelClassesRecursive(getClass().getPackage().getName());
for (ClassPath.ClassInfo info : classes) {
Class<?> clz = info.load();
if (!API.class.equals(clz) && API.class.isAssignableFrom(clz)) {
System.out.println("Loading API: " + clz.getName());
API obj = (API) clz.newInstance();
System.out.println("Registered API: " + obj);
count++;
}
}
System.out.println("Total " + count + " API(s) loaded.");
public void test() {
Reflections reflections = new Reflections(getClass().getPackage().getName());
Set<Class<? extends API>> set = reflections.getSubTypesOf(API.class);
assert set.size() == 14;
}
}

View File

@@ -1,20 +1,18 @@
package love.sola.netsupport.wechat;
package love.sola.netsupport.config;
import org.junit.Test;
import java.util.Date;
/**
* ***********************************************
* Created by Sola on 2015/12/3.
* Created by Sola on 2016/3/26.
* Don't modify this source without my agreement
* ***********************************************
*/
public class TestDate {
public class ReflectionTest {
@Test
public void test() {
System.out.println(new Date());
public void testLang() {
assert Lang.messages != null;
}
}

View File

@@ -1,6 +1,5 @@
package love.sola.netsupport.wechat;
package love.sola.netsupport.enums;
import love.sola.netsupport.enums.Block;
import org.junit.Test;
/**
@@ -9,11 +8,21 @@ import org.junit.Test;
* Don't modify this source without my agreement
* ***********************************************
*/
public class TestReflection {
public class ReflectionTest {
@Test
public void testBlock() {
assert Block.inverseMap != null;
}
@Test
public void testAccess() {
assert Access.inverseMap != null;
}
@Test
public void testStatus() {
assert Status.inverseMap != null;
}
}

View File

@@ -1,6 +1,5 @@
package love.sola.netsupport.wechat;
package love.sola.netsupport.util;
import love.sola.netsupport.util.RSAUtil;
import org.apache.commons.codec.binary.Base64;
import org.junit.Test;
import org.mindrot.jbcrypt.BCrypt;
@@ -16,7 +15,7 @@ import java.security.spec.X509EncodedKeySpec;
* Don't modify this source without my agreement
* ***********************************************
*/
public class TestEncrypt {
public class EncryptTest {
@Test
public void testBCrypt() {

View File

@@ -1,11 +1,9 @@
package love.sola.netsupport.wechat;
package love.sola.netsupport.util;
import com.google.gson.*;
import love.sola.netsupport.config.Lang;
import love.sola.netsupport.enums.ISP;
import org.junit.Test;
import java.text.MessageFormat;
import java.util.Date;
/**
@@ -14,12 +12,7 @@ import java.util.Date;
* Don't modify this source without my agreement
* ***********************************************
*/
public class TestMessageFormat {
@Test
public void testLang() {
assert Lang.messages != null;
}
public class GsonTest {
@Test
public void testJsonDate() {
@@ -35,14 +28,4 @@ public class TestMessageFormat {
assert gson.toJson(ISP.TELECOM).equals("1");
}
@Test
public void testLong() {
assert "15838838438".equals(MessageFormat.format("{0,number,#}", 15838838438L));
}
@Test
public void testOpInfo() {
assert !Lang.format("Operator_Info", 1541, "Sola", 0, 0, 4).isEmpty();
}
}

View File

@@ -0,0 +1,34 @@
package love.sola.netsupport.util;
import com.google.common.net.UrlEscapers;
import org.junit.Test;
import java.io.UnsupportedEncodingException;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
/**
* ***********************************************
* Created by Sola on 2016/3/26.
* Don't modify this source without my agreement
* ***********************************************
*/
public class URLEncodeTest {
@Test
public void testEncode() throws UnsupportedEncodingException {
assertThat(
UrlEscapers.urlFragmentEscaper().escape("Test Title"),
equalTo("Test%20Title")
);
assertThat(
Redirect.success()
.title("Test Title")
.msg("Test Message")
.toString(),
equalTo("http://topaz.sinaapp.com/nm/v2/result.html?type=1&title=!!Test%20Title!!&msg=!!Test%20Message!!&")
);
}
}

View File

@@ -1,21 +0,0 @@
package love.sola.netsupport.wechat;
import org.junit.Test;
/**
* ***********************************************
* Created by Sola on 2015/11/26.
* Don't modify this source without my agreement
* ***********************************************
*/
public class TestRegex {
public static final String STUDENT_ID_REGEX = "^(2012|2013|2014|2015)[0-9]{9}";
@Test
public void testStudentId() {
assert !"2011130201233".matches(STUDENT_ID_REGEX);
assert "2015130201233".matches(STUDENT_ID_REGEX);
}
}