添加代码示例springboot-jwt

This commit is contained in:
yidao620 2018-02-27 19:08:19 +08:00
parent 4cc394aad7
commit e7f352ade5
54 changed files with 5302 additions and 0 deletions

17
springboot-jwt/.gitignore vendored Normal file
View File

@ -0,0 +1,17 @@
# 此为注释– 将被Git 忽略
# /结尾表示是目录,忽略目录和目录下的所有件
# /开头表示根目录,否则是.gitignore的相对目录
# !开头表示反选
.idea/
target/
*.iml
*.ipr
*.iws
*.log
.svn/
.project
rebel.xml
.rebel-remote.xml.*
swagger.json
swagger.adoc

20
springboot-jwt/LICENSE Normal file
View File

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2018 Xiong Neng
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

20
springboot-jwt/README.md Normal file
View File

@ -0,0 +1,20 @@
## 简介
一般来讲对于RESTful API都会有认证(Authentication)和授权(Authorization)过程保证API的安全性。
采用TOKEN认证这种方式也是再HTTP头中使用Authorization: Bearer <token>使用最广泛的TOKEN是JWT通过签名过的TOKEN。
基于Shiro+JWT可实现Token认证方式
## 测试
启动应用后,先访问登录接口,使用参数用户名=admin/密码=12345678拿到token后再访问其他接口。
## 许可证
Copyright (c) 2018 Xiong Neng
基于 MIT 协议发布: <http://www.opensource.org/licenses/MIT>

136
springboot-jwt/pom.xml Normal file
View File

@ -0,0 +1,136 @@
<?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>
<groupId>com.xncoding</groupId>
<artifactId>springboot-jwt</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot-jwt</name>
<description>集成JWT实现接口权限认证</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>com.vaadin.external.google</groupId>
<artifactId>android-json</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- shiro 权限控制 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- shiro ehcache (shiro缓存)-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.4.0</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<!--<proc>none</proc>-->
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20</version>
<configuration>
<systemPropertyVariables>
<swaggerOutputDir>${project.basedir}/src/main/resources/swagger</swaggerOutputDir>
<asciiDocOutputDir>${project.basedir}/src/main/resources/swagger/swagger</asciiDocOutputDir>
</systemPropertyVariables>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
</project>

72
springboot-jwt/run.sh Normal file
View File

@ -0,0 +1,72 @@
#!/bin/bash
# 项目自动更新脚本
# 先clone相应的分支下来
# git clone ssh://git@120.24.173.142:7999/xxx.git
# 远程调试启动:
# nohup java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -Xms512m -Xmx1024m -jar -Dspring.profiles.active=${profile} ${jarfile} >/dev/null 2>&1 &
function start {
profile="$1"
echo "启动环境profile=${profile}"
jarfile=$(ls target/*.jar)
if [[ "$?" == "0" ]]; then
stop $profile $jarfile
fi
branch=$(git branch |awk '{print $2}')
git pull origin ${branch}
echo "更新完代码开始重新打包"
mvn clean && mvn clean && mvn package -DskipTests=true
if [[ "$?" != "0" ]]; then
echo "编译出错,退出!"
exit 1
fi
echo "nohup java -Xms512m -Xmx1024m -jar -Dspring.profiles.active=${profile} ${jarfile} >/dev/null 2>&1 &"
nohup java -Xms512m -Xmx1024m -jar -Dspring.profiles.active=${profile} ${jarfile} >/dev/null 2>&1 &
echo "启动应用中,请查看日志文件..."
}
function stop {
profile="$1"
jarfile="$2"
ps aux | grep "${jarfile}" | grep "spring.profiles.active=${profile}" | grep -v grep > /dev/null
if [[ "$?" == "0" ]]; then
echo "该应用还在跑,我先停了它"
pid=$(ps aux | grep "${jarfile}" | grep "spring.profiles.active=${profile}" | grep -v grep |awk '{print $2}')
if [[ "$pid" != "" ]]; then
kill -9 $pid
fi
echo "停止应用成功..."
fi
}
if [[ "$1" == "start" ]]; then
if [[ "$#" < 2 ]]; then
echo "请输入正确参数:./epay.sh start {profile}"
exit 1
fi
profile="$2"
if [[ "$profile" != "dev" && "$profile" != "test" && "$profile" != "show" && "$profile" != "production" ]]; then
echo "参数错误请输入正确的profile参数使用方法"
echo "./epay.sh start {profile} ==> 启动应用,{profile}取值dev|test|show|production"
exit 1
fi
start "${profile}"
elif [[ "$1" == "stop" ]]; then
if [[ "$#" < 2 ]]; then
echo "请输入正确参数:./epay.sh stop {profile}"
exit 1
fi
profile="$2"
if [[ "$profile" != "dev" && "$profile" != "test" && "$profile" != "show" && "$profile" != "production" ]]; then
echo "参数错误请输入正确的profile参数使用方法"
echo "./epay.sh stop {profile} ==> 停止应用,{profile}取值dev|test|show|production"
exit 1
fi
jarfile=$(ls target/*.jar)
stop $profile $jarfile
else
echo "参数错误,使用方法:{}参数是必填的,[]参数可选"
echo "./epay.sh start {profile} ==> 启动应用,{profile}取值dev|test|show|production"
echo "./epay.sh stop {profile} ==> 停止应用,{profile}取值dev|test|show|production"
exit 1
fi

View File

@ -0,0 +1,12 @@
package com.xncoding.jwt;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -0,0 +1,48 @@
package com.xncoding.jwt.api;
import com.xncoding.jwt.api.model.BaseResponse;
import org.apache.shiro.ShiroException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
/**
* 注意这个统一异常处理器只对认证过的用户调用接口中的异常有作用对AuthenticationException没有用
*/
@RestControllerAdvice
public class ExceptionController {
// 捕捉shiro的异常
@ResponseStatus(HttpStatus.UNAUTHORIZED)
@ExceptionHandler(ShiroException.class)
public BaseResponse handle401(ShiroException e) {
return new BaseResponse(false, "shiro的异常", null);
}
// 捕捉UnauthorizedException
@ResponseStatus(HttpStatus.UNAUTHORIZED)
@ExceptionHandler(UnauthorizedException.class)
public BaseResponse handle401() {
return new BaseResponse(false, "UnauthorizedException", null);
}
// 捕捉其他所有异常
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public BaseResponse globalException(HttpServletRequest request, Throwable ex) {
return new BaseResponse(false, "其他异常", null);
}
private HttpStatus getStatus(HttpServletRequest request) {
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
if (statusCode == null) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
return HttpStatus.valueOf(statusCode);
}
}

View File

@ -0,0 +1,72 @@
package com.xncoding.jwt.api;
import com.xncoding.jwt.api.model.BaseResponse;
import com.xncoding.jwt.api.model.LoginParam;
import com.xncoding.jwt.common.util.JWTUtil;
import com.xncoding.jwt.dao.entity.ManagerInfo;
import com.xncoding.jwt.service.ManagerInfoService;
import com.xncoding.jwt.shiro.ShiroKit;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.UnauthorizedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* 登录接口类
*/
@RestController
public class LoginController {
@Resource
private ManagerInfoService managerInfoService;
private static final Logger _logger = LoggerFactory.getLogger(LoginController.class);
@PostMapping("/login")
public BaseResponse<String> login(@RequestHeader(name="Content-Type", defaultValue = "application/json") String contentType,
@RequestBody LoginParam loginParam) {
_logger.info("用户请求登录获取Token");
String username = loginParam.getUsername();
String password = loginParam.getPassword();
String appid = loginParam.getAppid();
String imei = loginParam.getImei();
ManagerInfo user = managerInfoService.findByUsername(username);
//用户名+随机数
String salt = user.getSalt();
//原密码
String encodedPassword = ShiroKit.md5(password, username + salt);
if (user.getPassword().equals(encodedPassword)) {
if (StringUtils.isNotEmpty(appid) && StringUtils.isNotEmpty(imei)) {
return new BaseResponse<>(true, "Login success", JWTUtil.signSocket(username, encodedPassword, appid, imei));
}
return new BaseResponse<>(true, "Login success", JWTUtil.sign(username, encodedPassword));
} else {
throw new UnauthorizedException();
}
}
@PostMapping("/notifyLogin")
public BaseResponse<String> notifyLogin(@RequestHeader(name="Content-Type", defaultValue = "application/json") String contentType,
@RequestBody LoginParam loginParam) {
_logger.info("登录用户推送请求登录获取Token");
String username = loginParam.getUsername();
String password = loginParam.getPassword();
ManagerInfo user = managerInfoService.findByUsername(username);
if (user.getPassword().equals(password)) {
return new BaseResponse<>(true, "Login success", JWTUtil.sign(username, password));
} else {
throw new UnauthorizedException();
}
}
@GetMapping(path = "/401")
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public BaseResponse unauthorized() {
return new BaseResponse<>(false, "Unauthorized", null);
}
}

View File

@ -0,0 +1,28 @@
package com.xncoding.jwt.api;
import com.xncoding.jwt.api.model.BaseResponse;
import com.xncoding.jwt.api.model.UnbindParam;
import org.apache.shiro.authz.annotation.RequiresUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
/**
* 通知接口类
*/
@RestController
@RequestMapping(value = "/notify")
public class NotifyController {
private static final Logger _logger = LoggerFactory.getLogger(NotifyController.class);
@PostMapping("/unbind")
@RequiresUser
public BaseResponse unbind(@RequestHeader(name="Content-Type", defaultValue = "application/json") String contentType,
@RequestHeader(name="Authorization", defaultValue="token") String token,
@RequestBody UnbindParam unbindParam) {
_logger.info("解绑通知接口start");
return new BaseResponse<>(true, "解绑通知发送成功", null);
}
}

View File

@ -0,0 +1,267 @@
package com.xncoding.jwt.api;
import com.xncoding.jwt.api.model.*;
import com.xncoding.jwt.common.dao.entity.Pos;
import com.xncoding.jwt.common.dao.entity.Project;
import com.xncoding.jwt.service.ApiService;
import com.xncoding.jwt.service.ManagerInfoService;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Date;
/**
* 机具管理API接口类
*/
@RestController
@RequestMapping(value = "/api/v1")
public class PublicController {
@Resource
private ApiService apiService;
@Resource
private ManagerInfoService managerInfoService;
private static final Logger _logger = LoggerFactory.getLogger(PublicController.class);
/**
* 入网绑定查询接口
*
* @return 是否入网
*/
@RequestMapping(value = "/join", method = RequestMethod.GET)
@RequiresUser
public JoinBindResponse join(@RequestHeader(name="Accept", defaultValue = "application/json", required = false) String accept,
@RequestHeader(name="Authorization", defaultValue="token") String token,
@RequestParam("imei") String imei) {
_logger.info("入网查询接口 start....");
JoinBindResponse result = new JoinBindResponse();
int posCount = apiService.selectCount(imei);
if (posCount > 0) {
// 如果入网了再去查询是否绑定了网点
int bindCount = apiService.selectBindCount(imei);
Pos pos = apiService.selectByImei(imei);
result.setPosState(pos.getPosState());
if (bindCount == 0) {
result.setSuccess(false);
result.setCode(2);
result.setMsg("已入网但尚未绑定网点");
} else {
result.setSuccess(true);
result.setCode(1);
result.setMsg("已入网并绑定了网点");
}
} else {
result.setSuccess(false);
result.setCode(3);
result.setMsg("未入网");
}
return result;
}
/**
* 请求入网接口
*
* @return 处理结果
*/
@RequestMapping(value = "/join", method = RequestMethod.POST)
@RequiresUser
public ResponseEntity<BaseResponse> doJoin(@RequestHeader(name="Content-Type", defaultValue = "application/json") String contentType,
@RequestHeader(name="Authorization", defaultValue="token") String token,
@RequestBody PosParam posParam) {
_logger.info("请求入网接口 start....");
BaseResponse result = new BaseResponse();
// imei码约束检查
if (StringUtils.isEmpty(posParam.getImei()) || posParam.getImei().length() > 32) {
result.setSuccess(false);
result.setMsg("IMEI码长度不是1-32位入网失败。");
return new ResponseEntity<>(result, HttpStatus.OK);
}
// 序列号SN约束检查
if (StringUtils.isEmpty(posParam.getSn()) || posParam.getSn().length() > 64) {
result.setSuccess(false);
result.setMsg("序列号长度不是1-64位入网失败。");
return new ResponseEntity<>(result, HttpStatus.OK);
}
// 机具型号约束检查
if (StringUtils.isEmpty(posParam.getSeries()) || posParam.getSeries().length() > 32) {
result.setSuccess(false);
result.setMsg("机具型号不是1-32位入网失败。");
return new ResponseEntity<>(result, HttpStatus.OK);
}
// Android版本约束检查
if (StringUtils.isEmpty(posParam.getAndroidVersion()) || posParam.getAndroidVersion().length() > 32) {
result.setSuccess(false);
result.setMsg("Android版本号不是1-32位入网失败。");
return new ResponseEntity<>(result, HttpStatus.OK);
}
// 版本号约束检查
if (StringUtils.isEmpty(posParam.getVersion()) || posParam.getVersion().length() > 32) {
result.setSuccess(false);
result.setMsg("版本号不是1-32位入网失败。");
return new ResponseEntity<>(result, HttpStatus.OK);
}
// 归属网点约束检查
if (StringUtils.isEmpty(posParam.getLocation()) || posParam.getLocation().length() > 64) {
result.setSuccess(false);
result.setMsg("归属网点不是1-64位入网失败。");
return new ResponseEntity<>(result, HttpStatus.OK);
}
// 产权方约束检查
if (StringUtils.isEmpty(posParam.getOwner()) || posParam.getOwner().length() > 64) {
result.setSuccess(false);
result.setMsg("产权方不是1-64位入网失败。");
return new ResponseEntity<>(result, HttpStatus.OK);
}
// 应用ID约束检查
if (StringUtils.isEmpty(posParam.getApplicationId()) || posParam.getApplicationId().length() > 64) {
result.setSuccess(false);
result.setMsg("应用ID不是1-64位入网失败。");
return new ResponseEntity<>(result, HttpStatus.OK);
}
// 备注约束检查
if (StringUtils.isNotEmpty(posParam.getTips()) && posParam.getTips().length() > 255) {
result.setSuccess(false);
result.setMsg("备注超过255个字符入网失败。");
return new ResponseEntity<>(result, HttpStatus.OK);
}
Pos pos = new Pos();
Date now = new Date();
pos.setJointime(now);
pos.setBindtime(now);
BeanUtils.copyProperties(posParam, pos);
// 根据applicationId设置归属项目ID
Project project = apiService.selectProjectByApplicationId(posParam.getApplicationId());
if (project == null) {
result.setSuccess(false);
result.setMsg("Application Id不正确入网失败。");
return new ResponseEntity<>(result, HttpStatus.OK);
}
// 重复检查
int posCount = apiService.selectCount(posParam.getImei());
if (posCount > 0) {
result.setSuccess(false);
result.setMsg("入网失败,该机具之前已经入网了。");
return new ResponseEntity<>(result, HttpStatus.OK);
}
// 插入一条新纪录
pos.setProjectId(project.getId());
int insert = apiService.insertPos(pos);
if (insert > 0) {
result.setSuccess(true);
result.setMsg("入网成功");
return new ResponseEntity<>(result, HttpStatus.CREATED);
} else {
result.setSuccess(false);
result.setMsg("入网失败,请联系管理员。");
return new ResponseEntity<>(result, HttpStatus.OK);
}
}
/**
* 请求绑定网点接口
*
* @return 处理结果
*/
@RequestMapping(value = "/bind", method = RequestMethod.POST)
@RequiresUser
public ResponseEntity<BaseResponse> doBind(@RequestHeader(name="Content-Type", defaultValue = "application/json") String contentType,
@RequestHeader(name="Authorization", defaultValue="token") String token,
@RequestBody BindParam bindParam) {
_logger.info("请求绑定网点接口 start....");
BaseResponse result = new BaseResponse();
// imei码约束检查
if (StringUtils.isEmpty(bindParam.getImei()) || bindParam.getImei().length() > 32) {
result.setSuccess(false);
result.setMsg("IMEI码长度不是1-32位绑定网点失败。");
return new ResponseEntity<>(result, HttpStatus.OK);
}
// 归属网点约束检查
if (StringUtils.isEmpty(bindParam.getLocation()) || bindParam.getLocation().length() > 64) {
result.setSuccess(false);
result.setMsg("归属网点不是1-64位绑定网点失败。");
return new ResponseEntity<>(result, HttpStatus.OK);
}
Pos pos = apiService.selectByImei(bindParam.getImei());
if (pos == null) {
result.setSuccess(false);
result.setMsg("该POS机尚未入网。");
return new ResponseEntity<>(result, HttpStatus.OK);
}
Pos pos2 = apiService.selectBindByImei(bindParam.getImei());
if (pos2 != null) {
result.setSuccess(false);
result.setMsg("该POS机已经绑定了网点请先解绑。");
return new ResponseEntity<>(result, HttpStatus.OK);
}
pos.setLocation(bindParam.getLocation());
pos.setUpdatedTime(new Date());
apiService.bindLocation(pos);
result.setSuccess(true);
result.setMsg("绑定网点成功");
return new ResponseEntity<>(result, HttpStatus.OK);
}
/**
* 报告位置接口
*
* @return 报告结果
*/
@RequestMapping(value = "/report", method = RequestMethod.POST)
@RequiresUser
public BaseResponse report(@RequestHeader(name="Content-Type", defaultValue = "application/json") String contentType,
@RequestHeader(name="Authorization", defaultValue="token") String token,
@RequestBody ReportParam param) {
_logger.info("定时报告接口 start....");
BaseResponse result = new BaseResponse();
// IMEI码约束检查
if (StringUtils.isEmpty(param.getImei()) || param.getImei().length() > 32) {
result.setSuccess(false);
result.setMsg("IMEI码不是1-32位心跳报告失败。");
return result;
}
// 地址约束检查
if (StringUtils.isEmpty(param.getLocation()) || param.getLocation().length() > 255) {
result.setSuccess(false);
result.setMsg("地址不是1-255位心跳报告失败。");
return result;
}
int r = apiService.report(param);
if (r > 0) {
result.setSuccess(true);
result.setMsg("心跳报告成功");
} else {
result.setSuccess(false);
result.setMsg("该POS机还没有入网心跳报告失败。");
}
return result;
}
/**
* 版本检查接口
*
* @return 版本检查结果
*/
@RequestMapping(value = "/version", method = RequestMethod.POST)
@RequiresUser
public VersionResult version(@RequestHeader(name="Content-Type", defaultValue = "application/json") String contentType,
@RequestHeader(name="Authorization", defaultValue="token") String token,
@RequestBody VersionParam param) {
_logger.info("版本检查接口 start....");
return apiService.selectPublishCount(param);
}
}

View File

@ -0,0 +1,60 @@
package com.xncoding.jwt.api.model;
/**
* API接口的基础返回类
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/7
*/
public class BaseResponse<T> {
/**
* 是否成功
*/
private boolean success;
/**
* 说明
*/
private String msg;
/**
* 返回数据
*/
private T data;
public BaseResponse() {
}
public BaseResponse(boolean success, String msg, T data) {
this.success = success;
this.msg = msg;
this.data = data;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}

View File

@ -0,0 +1,35 @@
package com.xncoding.jwt.api.model;
/**
* POS绑定网点参数
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/7
*/
public class BindParam {
/**
* 机具IMEI码
*/
private String imei;
/**
* 归属网点
*/
private String location;
public String getImei() {
return imei;
}
public void setImei(String imei) {
this.imei = imei;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}

View File

@ -0,0 +1,36 @@
package com.xncoding.jwt.api.model;
/**
* 入网绑定返回
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/16
*/
public class JoinBindResponse<T> extends BaseResponse<T> {
/**
* 返回码 1:已入网并绑定了网点 2:已入网但尚未绑定网点 3:未入网
*/
private int code;
/**
* 机具状态: 1:正常 2:故障 3:维修中(返厂) 4:已禁用(丢失) 5:已停用(回收)
*/
private Integer posState;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public Integer getPosState() {
return posState;
}
public void setPosState(Integer posState) {
this.posState = posState;
}
}

View File

@ -0,0 +1,59 @@
package com.xncoding.jwt.api.model;
/**
* 登录认证接口参数
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/9
*/
public class LoginParam {
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* Application ID
*/
private String appid;
/**
* IMEI码
*/
private String imei;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getAppid() {
return appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getImei() {
return imei;
}
public void setImei(String imei) {
this.imei = imei;
}
}

View File

@ -0,0 +1,119 @@
package com.xncoding.jwt.api.model;
/**
* POS入网参数
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/7
*/
public class PosParam {
/**
* 机具IMEI码
*/
private String imei;
/**
* 序列号(SN)
*/
private String sn;
/**
* 机具型号
*/
private String series;
/**
* Android版本
*/
private String androidVersion;
/**
* 版本号
*/
private String version;
/**
* 归属网点
*/
private String location;
/**
* 产权方
*/
private String owner;
/**
* 备注
*/
private String tips;
/**
* 应用ID
*/
private String applicationId;
public String getImei() {
return imei;
}
public void setImei(String imei) {
this.imei = imei;
}
public String getSn() {
return sn;
}
public void setSn(String sn) {
this.sn = sn;
}
public String getSeries() {
return series;
}
public void setSeries(String series) {
this.series = series;
}
public String getAndroidVersion() {
return androidVersion;
}
public void setAndroidVersion(String androidVersion) {
this.androidVersion = androidVersion;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getTips() {
return tips;
}
public void setTips(String tips) {
this.tips = tips;
}
public String getApplicationId() {
return applicationId;
}
public void setApplicationId(String applicationId) {
this.applicationId = applicationId;
}
}

View File

@ -0,0 +1,35 @@
package com.xncoding.jwt.api.model;
/**
* 报告参数
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/7
*/
public class ReportParam {
/**
* IMEI码
*/
private String imei;
/**
* 位置
*/
private String location;
public String getImei() {
return imei;
}
public void setImei(String imei) {
this.imei = imei;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}

View File

@ -0,0 +1,35 @@
package com.xncoding.jwt.api.model;
/**
* 解绑通知参数
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/9
*/
public class UnbindParam {
/**
* IMEI码
*/
private String imei;
/**
* 网点
*/
private String location;
public String getImei() {
return imei;
}
public void setImei(String imei) {
this.imei = imei;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}

View File

@ -0,0 +1,47 @@
package com.xncoding.jwt.api.model;
/**
* APP版本检查接口参数
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/9
*/
public class VersionParam {
/**
* 机具IMEI码
*/
private String imei;
/**
* 应用ID
*/
private String applicationId;
/**
* 当前版本号
*/
private String version;
public String getApplicationId() {
return applicationId;
}
public void setApplicationId(String applicationId) {
this.applicationId = applicationId;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getImei() {
return imei;
}
public void setImei(String imei) {
this.imei = imei;
}
}

View File

@ -0,0 +1,85 @@
package com.xncoding.jwt.api.model;
import java.util.Date;
/**
* 版本检查结果
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/9
*/
public class VersionResult {
/**
* 是否发现新版本
*/
private boolean findNew;
/**
* APP名称
*/
private String appName;
/**
* 新版本号
*/
private String version;
/**
* 新版本说明
*/
private String tips;
/**
* 新版本发布时间
*/
private Date publishtime;
/**
* 新版本下载地址
*/
private String downloadUrl;
public boolean isFindNew() {
return findNew;
}
public void setFindNew(boolean findNew) {
this.findNew = findNew;
}
public String getDownloadUrl() {
return downloadUrl;
}
public void setDownloadUrl(String downloadUrl) {
this.downloadUrl = downloadUrl;
}
public String getAppName() {
return appName;
}
public void setAppName(String appName) {
this.appName = appName;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getTips() {
return tips;
}
public void setTips(String tips) {
this.tips = tips;
}
public Date getPublishtime() {
return publishtime;
}
public void setPublishtime(Date publishtime) {
this.publishtime = publishtime;
}
}

View File

@ -0,0 +1,37 @@
package com.xncoding.jwt.common.constant;
import java.util.ArrayList;
import java.util.List;
/**
* 常量列表
*
* @author XiongNeng
* @version 1.0
* @since 2018/01/07
*/
public class ConstantsList {
// 应收款项列表
public static final List<String> INCOME_TYPE_LIST = new ArrayList<String>() {{
add("租金");
add("市场管理费");
add("物业管理费");
add("其他");
}};
// 市场列表
public static final List<String> MARKET_LIST = new ArrayList<String>() {{
add("一期市场");
add("二期市场");
add("三期市场");
}};
// 业态
public static final List<String> BUSINESS_LIST = new ArrayList<String>() {{
add("男装");
add("女装");
add("玩具");
add("餐饮");
add("家具");
}};
}

View File

@ -0,0 +1,80 @@
package com.xncoding.jwt.common.constant;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
/**
* 表常量字典
*
* @author XiongNeng
* @version 1.0
* @since 2018/01/07
*/
public class DictMap {
/**
* 后台管理用户表 - 状态(1:正常 2:禁用)
*/
public static final String KEY_USER_STATUS = "t_manager.status";
/**
* POS机表 - 机具状态(1:正常 2:故障 3:维修中(返厂) 4:已禁用(丢失) 5:已停用(回收))
*/
public static final String KEY_POS_POS_STATUS = "t_pos.pos_state";
/**
* POS机监控表 - 在线状态(1:在线 2:离线)
*/
public static final String KEY_POS_MONITOR_STATUS = "t_pos_monitor.online_state";
/**
* APP表 - 发布范围(1:全网发布 2:灰度发布)
*/
public static final String KEY_APP_PUBLISH_RANGE = "t_app.publish_range";
/**
* 内部用ClassName + FieldName为key
*/
private static final Map<String, TreeMap<Integer, String>> _imap = new HashMap<>();
static {
_imap.put(KEY_USER_STATUS, new TreeMap<Integer, String>() {{
put(1, "正常");
put(2, "禁用");
}});
_imap.put(KEY_POS_POS_STATUS, new TreeMap<Integer, String>() {{
put(1, "正常");
put(2, "故障");
put(3, "维修中(返厂)");
put(4, "已禁用(丢失)");
put(5, "已停用(回收)");
}});
_imap.put(KEY_POS_MONITOR_STATUS, new TreeMap<Integer, String>() {{
put(1, "在线");
put(2, "离线");
}});
_imap.put(KEY_APP_PUBLISH_RANGE, new TreeMap<Integer, String>() {{
put(1, "全网发布");
put(2, "灰度发布");
}});
}
/**
* 根据字典类型key获取某个字典Map
*
* @param type 常量类型
* @return 字典Map
*/
public static TreeMap<Integer, String> map(String type) {
return _imap.get(type);
}
/**
* 根据字典类型和数字获取对应的字符串
*
* @param type 字典类型
* @param key 数字
* @return 对应的字符串
*/
public static String value(String type, Integer key) {
return key != null ? map(type).get(key) : null;
}
}

View File

@ -0,0 +1,264 @@
package com.xncoding.jwt.common.dao.entity;
import java.io.Serializable;
import java.util.Date;
/**
* APP表
*
* @author 熊能
* @version 1.0
* @since 2018/01/02
*/
public class App {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Integer id;
/**
* 应用编号
*/
private String applicationId;
/**
* 应用名称
*/
private String name;
/**
* 版本号
*/
private String version;
/**
* 版本说明
*/
private String tips;
/**
* 归属项目ID
*/
private Integer projectId;
/**
* 发布时间
*/
private Date publishtime;
/**
* 发布范围 1:全网发布 2:灰度发布
*/
private Integer publishRange;
/**
* 操作者ID
*/
private Integer operatorId;
/**
* 创建时间
*/
private Date createdTime;
/**
* 更新时间
*/
private Date updatedTime;
/**
* 获取 主键ID.
*
* @return 主键ID.
*/
public Integer getId() {
return id;
}
/**
* 设置 主键ID.
*
* @param id 主键ID.
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取 应用编号.
*
* @return 应用编号.
*/
public String getApplicationId() {
return applicationId;
}
/**
* 设置 应用编号.
*
* @param applicationId 应用编号.
*/
public void setApplicationId(String applicationId) {
this.applicationId = applicationId;
}
/**
* 获取 应用名称.
*
* @return 应用名称.
*/
public String getName() {
return name;
}
/**
* 设置 应用名称.
*
* @param name 应用名称.
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取 版本号.
*
* @return 版本号.
*/
public String getVersion() {
return version;
}
/**
* 设置 版本号.
*
* @param version 版本号.
*/
public void setVersion(String version) {
this.version = version;
}
/**
* 获取 版本说明.
*
* @return 版本说明.
*/
public String getTips() {
return tips;
}
/**
* 设置 版本说明.
*
* @param tips 版本说明.
*/
public void setTips(String tips) {
this.tips = tips;
}
/**
* 获取 归属项目ID.
*
* @return 归属项目ID.
*/
public Integer getProjectId() {
return projectId;
}
/**
* 设置 归属项目ID.
*
* @param projectId 归属项目ID.
*/
public void setProjectId(Integer projectId) {
this.projectId = projectId;
}
/**
* 获取 发布时间.
*
* @return 发布时间.
*/
public Date getPublishtime() {
return publishtime;
}
/**
* 设置 发布时间.
*
* @param publishtime 发布时间.
*/
public void setPublishtime(Date publishtime) {
this.publishtime = publishtime;
}
/**
* 获取 发布范围 1:全网发布 2:灰度发布.
*
* @return 发布范围 1:全网发布 2:灰度发布.
*/
public Integer getPublishRange() {
return publishRange;
}
/**
* 设置 发布范围 1:全网发布 2:灰度发布.
*
* @param publishRange 发布范围 1:全网发布 2:灰度发布.
*/
public void setPublishRange(Integer publishRange) {
this.publishRange = publishRange;
}
/**
* 获取 操作者ID.
*
* @return 操作者ID.
*/
public Integer getOperatorId() {
return operatorId;
}
/**
* 设置 操作者ID.
*
* @param operatorId 操作者ID.
*/
public void setOperatorId(Integer operatorId) {
this.operatorId = operatorId;
}
/**
* 获取 创建时间.
*
* @return 创建时间.
*/
public Date getCreatedTime() {
return createdTime;
}
/**
* 设置 创建时间.
*
* @param createdTime 创建时间.
*/
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
/**
* 获取 更新时间.
*
* @return 更新时间.
*/
public Date getUpdatedTime() {
return updatedTime;
}
/**
* 设置 更新时间.
*
* @param updatedTime 更新时间.
*/
public void setUpdatedTime(Date updatedTime) {
this.updatedTime = updatedTime;
}
protected Serializable pkVal() {
return this.id;
}
}

View File

@ -0,0 +1,132 @@
package com.xncoding.jwt.common.dao.entity;
import java.io.Serializable;
import java.util.Date;
/**
* APP发布表
*
* @author 熊能
* @version 1.0
* @since 2018/01/02
*/
public class AppPublish {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Integer id;
/**
* APP主键
*/
private Integer appId;
/**
* POS主键
*/
private Integer posId;
/**
* 创建时间
*/
private Date createdTime;
/**
* 更新时间
*/
private Date updatedTime;
/**
* 获取 主键ID.
*
* @return 主键ID.
*/
public Integer getId() {
return id;
}
/**
* 设置 主键ID.
*
* @param id 主键ID.
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取 APP主键.
*
* @return APP主键.
*/
public Integer getAppId() {
return appId;
}
/**
* 设置 APP主键.
*
* @param appId APP主键.
*/
public void setAppId(Integer appId) {
this.appId = appId;
}
/**
* 获取 POS主键.
*
* @return POS主键.
*/
public Integer getPosId() {
return posId;
}
/**
* 设置 POS主键.
*
* @param posId POS主键.
*/
public void setPosId(Integer posId) {
this.posId = posId;
}
/**
* 获取 创建时间.
*
* @return 创建时间.
*/
public Date getCreatedTime() {
return createdTime;
}
/**
* 设置 创建时间.
*
* @param createdTime 创建时间.
*/
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
/**
* 获取 更新时间.
*
* @return 更新时间.
*/
public Date getUpdatedTime() {
return updatedTime;
}
/**
* 设置 更新时间.
*
* @param updatedTime 更新时间.
*/
public void setUpdatedTime(Date updatedTime) {
this.updatedTime = updatedTime;
}
protected Serializable pkVal() {
return this.id;
}
}

View File

@ -0,0 +1,242 @@
package com.xncoding.jwt.common.dao.entity;
import java.io.Serializable;
import java.util.Date;
/**
* 后台管理用户表
*
* @author 熊能
* @version 1.0
* @since 2018/01/02
*/
public class Manager {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Integer id;
/**
* 账号
*/
private String username;
/**
* 名字
*/
private String name;
/**
* 密码
*/
private String password;
/**
* md5密码盐
*/
private String salt;
/**
* 联系电话
*/
private String phone;
/**
* 备注
*/
private String tips;
/**
* 状态 1:正常 2:禁用
*/
private Integer state;
/**
* 创建时间
*/
private Date createdTime;
/**
* 更新时间
*/
private Date updatedTime;
/**
* 获取 主键ID.
*
* @return 主键ID.
*/
public Integer getId() {
return id;
}
/**
* 设置 主键ID.
*
* @param id 主键ID.
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取 账号.
*
* @return 账号.
*/
public String getUsername() {
return username;
}
/**
* 设置 账号.
*
* @param username 账号.
*/
public void setUsername(String username) {
this.username = username;
}
/**
* 获取 名字.
*
* @return 名字.
*/
public String getName() {
return name;
}
/**
* 设置 名字.
*
* @param name 名字.
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取 密码.
*
* @return 密码.
*/
public String getPassword() {
return password;
}
/**
* 设置 密码.
*
* @param password 密码.
*/
public void setPassword(String password) {
this.password = password;
}
/**
* 获取 md5密码盐.
*
* @return md5密码盐.
*/
public String getSalt() {
return salt;
}
/**
* 设置 md5密码盐.
*
* @param salt md5密码盐.
*/
public void setSalt(String salt) {
this.salt = salt;
}
/**
* 获取 联系电话.
*
* @return 联系电话.
*/
public String getPhone() {
return phone;
}
/**
* 设置 联系电话.
*
* @param phone 联系电话.
*/
public void setPhone(String phone) {
this.phone = phone;
}
/**
* 获取 备注.
*
* @return 备注.
*/
public String getTips() {
return tips;
}
/**
* 设置 备注.
*
* @param tips 备注.
*/
public void setTips(String tips) {
this.tips = tips;
}
/**
* 获取 状态 1:正常 2:禁用.
*
* @return 状态 1:正常 2:禁用.
*/
public Integer getState() {
return state;
}
/**
* 设置 状态 1:正常 2:禁用.
*
* @param state 状态 1:正常 2:禁用.
*/
public void setState(Integer state) {
this.state = state;
}
/**
* 获取 创建时间.
*
* @return 创建时间.
*/
public Date getCreatedTime() {
return createdTime;
}
/**
* 设置 创建时间.
*
* @param createdTime 创建时间.
*/
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
/**
* 获取 更新时间.
*
* @return 更新时间.
*/
public Date getUpdatedTime() {
return updatedTime;
}
/**
* 设置 更新时间.
*
* @param updatedTime 更新时间.
*/
public void setUpdatedTime(Date updatedTime) {
this.updatedTime = updatedTime;
}
protected Serializable pkVal() {
return this.id;
}
}

View File

@ -0,0 +1,132 @@
package com.xncoding.jwt.common.dao.entity;
import java.io.Serializable;
import java.util.Date;
/**
* 用户角色关联表
*
* @author 熊能
* @version 1.0
* @since 2018/01/02
*/
public class ManagerRole {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Integer id;
/**
* 管理用户ID
*/
private Integer managerId;
/**
* 角色ID
*/
private Integer roleId;
/**
* 创建时间
*/
private Date createdTime;
/**
* 更新时间
*/
private Date updatedTime;
/**
* 获取 主键ID.
*
* @return 主键ID.
*/
public Integer getId() {
return id;
}
/**
* 设置 主键ID.
*
* @param id 主键ID.
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取 管理用户ID.
*
* @return 管理用户ID.
*/
public Integer getManagerId() {
return managerId;
}
/**
* 设置 管理用户ID.
*
* @param managerId 管理用户ID.
*/
public void setManagerId(Integer managerId) {
this.managerId = managerId;
}
/**
* 获取 角色ID.
*
* @return 角色ID.
*/
public Integer getRoleId() {
return roleId;
}
/**
* 设置 角色ID.
*
* @param roleId 角色ID.
*/
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
/**
* 获取 创建时间.
*
* @return 创建时间.
*/
public Date getCreatedTime() {
return createdTime;
}
/**
* 设置 创建时间.
*
* @param createdTime 创建时间.
*/
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
/**
* 获取 更新时间.
*
* @return 更新时间.
*/
public Date getUpdatedTime() {
return updatedTime;
}
/**
* 设置 更新时间.
*
* @param updatedTime 更新时间.
*/
public void setUpdatedTime(Date updatedTime) {
this.updatedTime = updatedTime;
}
protected Serializable pkVal() {
return this.id;
}
}

View File

@ -0,0 +1,198 @@
package com.xncoding.jwt.common.dao.entity;
import java.io.Serializable;
import java.util.Date;
/**
* 操作日志表
*
* @author 熊能
* @version 1.0
* @since 2018/01/02
*/
public class OperationLog {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Integer id;
/**
* 操作者ID
*/
private Integer operatorId;
/**
* 操作对象ID
*/
private Integer targetId;
/**
* 操作对象名称
*/
private String targetName;
/**
* 操作类型
*/
private String operateType;
/**
* 备注
*/
private String tips;
/**
* 创建时间
*/
private Date createdTime;
/**
* 更新时间
*/
private Date updatedTime;
/**
* 获取 主键ID.
*
* @return 主键ID.
*/
public Integer getId() {
return id;
}
/**
* 设置 主键ID.
*
* @param id 主键ID.
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取 操作者ID.
*
* @return 操作者ID.
*/
public Integer getOperatorId() {
return operatorId;
}
/**
* 设置 操作者ID.
*
* @param operatorId 操作者ID.
*/
public void setOperatorId(Integer operatorId) {
this.operatorId = operatorId;
}
/**
* 获取 操作对象ID.
*
* @return 操作对象ID.
*/
public Integer getTargetId() {
return targetId;
}
/**
* 设置 操作对象ID.
*
* @param targetId 操作对象ID.
*/
public void setTargetId(Integer targetId) {
this.targetId = targetId;
}
/**
* 获取 操作对象名称.
*
* @return 操作对象名称.
*/
public String getTargetName() {
return targetName;
}
/**
* 设置 操作对象名称.
*
* @param targetName 操作对象名称.
*/
public void setTargetName(String targetName) {
this.targetName = targetName;
}
/**
* 获取 操作类型.
*
* @return 操作类型.
*/
public String getOperateType() {
return operateType;
}
/**
* 设置 操作类型.
*
* @param operateType 操作类型.
*/
public void setOperateType(String operateType) {
this.operateType = operateType;
}
/**
* 获取 备注.
*
* @return 备注.
*/
public String getTips() {
return tips;
}
/**
* 设置 备注.
*
* @param tips 备注.
*/
public void setTips(String tips) {
this.tips = tips;
}
/**
* 获取 创建时间.
*
* @return 创建时间.
*/
public Date getCreatedTime() {
return createdTime;
}
/**
* 设置 创建时间.
*
* @param createdTime 创建时间.
*/
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
/**
* 获取 更新时间.
*
* @return 更新时间.
*/
public Date getUpdatedTime() {
return updatedTime;
}
/**
* 设置 更新时间.
*
* @param updatedTime 更新时间.
*/
public void setUpdatedTime(Date updatedTime) {
this.updatedTime = updatedTime;
}
protected Serializable pkVal() {
return this.id;
}
}

View File

@ -0,0 +1,132 @@
package com.xncoding.jwt.common.dao.entity;
import java.io.Serializable;
import java.util.Date;
/**
* 权限表
*
* @author 熊能
* @version 1.0
* @since 2018/01/02
*/
public class Permission {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Integer id;
/**
* 权限名称
*/
private String permission;
/**
* 权限说明
*/
private String description;
/**
* 创建时间
*/
private Date createdTime;
/**
* 更新时间
*/
private Date updatedTime;
/**
* 获取 主键ID.
*
* @return 主键ID.
*/
public Integer getId() {
return id;
}
/**
* 设置 主键ID.
*
* @param id 主键ID.
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取 权限名称.
*
* @return 权限名称.
*/
public String getPermission() {
return permission;
}
/**
* 设置 权限名称.
*
* @param permission 权限名称.
*/
public void setPermission(String permission) {
this.permission = permission;
}
/**
* 获取 权限说明.
*
* @return 权限说明.
*/
public String getDescription() {
return description;
}
/**
* 设置 权限说明.
*
* @param description 权限说明.
*/
public void setDescription(String description) {
this.description = description;
}
/**
* 获取 创建时间.
*
* @return 创建时间.
*/
public Date getCreatedTime() {
return createdTime;
}
/**
* 设置 创建时间.
*
* @param createdTime 创建时间.
*/
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
/**
* 获取 更新时间.
*
* @return 更新时间.
*/
public Date getUpdatedTime() {
return updatedTime;
}
/**
* 设置 更新时间.
*
* @param updatedTime 更新时间.
*/
public void setUpdatedTime(Date updatedTime) {
this.updatedTime = updatedTime;
}
protected Serializable pkVal() {
return this.id;
}
}

View File

@ -0,0 +1,352 @@
package com.xncoding.jwt.common.dao.entity;
import java.io.Serializable;
import java.util.Date;
/**
* POS机表
*
* @author 熊能
* @version 1.0
* @since 2018/01/02
*/
public class Pos {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Integer id;
/**
* 机具IMEI码
*/
private String imei;
/**
* 序列号(SN)
*/
private String sn;
/**
* 机具型号
*/
private String series;
/**
* Android版本
*/
private String androidVersion;
/**
* 版本号
*/
private String version;
/**
* 归属网点
*/
private String location;
/**
* 归属项目ID
*/
private Integer projectId;
/**
* 入网时间
*/
private Date jointime;
/**
* 绑定时间
*/
private Date bindtime;
/**
* 产权方
*/
private String owner;
/**
* 备注
*/
private String tips;
/**
* 机具状态: 1:正常 2:故障 3:维修中(返厂) 4:已禁用(丢失) 5:已停用(回收)
*/
private Integer posState;
/**
* 创建时间
*/
private Date createdTime;
/**
* 更新时间
*/
private Date updatedTime;
/**
* 获取 主键ID.
*
* @return 主键ID.
*/
public Integer getId() {
return id;
}
/**
* 设置 主键ID.
*
* @param id 主键ID.
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取 机具IMEI码.
*
* @return 机具IMEI码.
*/
public String getImei() {
return imei;
}
/**
* 设置 机具IMEI码.
*
* @param imei 机具IMEI码.
*/
public void setImei(String imei) {
this.imei = imei;
}
/**
* 获取 序列号(SN).
*
* @return 序列号(SN).
*/
public String getSn() {
return sn;
}
/**
* 设置 序列号(SN).
*
* @param sn 序列号(SN).
*/
public void setSn(String sn) {
this.sn = sn;
}
/**
* 获取 机具型号.
*
* @return 机具型号.
*/
public String getSeries() {
return series;
}
/**
* 设置 机具型号.
*
* @param series 机具型号.
*/
public void setSeries(String series) {
this.series = series;
}
/**
* 获取 Android版本.
*
* @return Android版本.
*/
public String getAndroidVersion() {
return androidVersion;
}
/**
* 设置 Android版本.
*
* @param androidVersion Android版本.
*/
public void setAndroidVersion(String androidVersion) {
this.androidVersion = androidVersion;
}
/**
* 获取 版本号.
*
* @return 版本号.
*/
public String getVersion() {
return version;
}
/**
* 设置 版本号.
*
* @param version 版本号.
*/
public void setVersion(String version) {
this.version = version;
}
/**
* 获取 归属网点.
*
* @return 归属网点.
*/
public String getLocation() {
return location;
}
/**
* 设置 归属网点.
*
* @param location 归属网点.
*/
public void setLocation(String location) {
this.location = location;
}
/**
* 获取 归属项目ID.
*
* @return 归属项目ID.
*/
public Integer getProjectId() {
return projectId;
}
/**
* 设置 归属项目ID.
*
* @param projectId 归属项目ID.
*/
public void setProjectId(Integer projectId) {
this.projectId = projectId;
}
/**
* 获取 入网时间.
*
* @return 入网时间.
*/
public Date getJointime() {
return jointime;
}
/**
* 设置 入网时间.
*
* @param jointime 入网时间.
*/
public void setJointime(Date jointime) {
this.jointime = jointime;
}
/**
* 获取 绑定时间.
*
* @return 绑定时间.
*/
public Date getBindtime() {
return bindtime;
}
/**
* 设置 绑定时间.
*
* @param bindtime 绑定时间.
*/
public void setBindtime(Date bindtime) {
this.bindtime = bindtime;
}
/**
* 获取 产权方.
*
* @return 产权方.
*/
public String getOwner() {
return owner;
}
/**
* 设置 产权方.
*
* @param owner 产权方.
*/
public void setOwner(String owner) {
this.owner = owner;
}
/**
* 获取 备注.
*
* @return 备注.
*/
public String getTips() {
return tips;
}
/**
* 设置 备注.
*
* @param tips 备注.
*/
public void setTips(String tips) {
this.tips = tips;
}
/**
* 获取 机具状态: 1:正常 2:故障 3:维修中(返厂) 4:已禁用(丢失) 5:已停用(回收).
*
* @return 机具状态: 1:正常 2:故障 3:维修中(返厂) 4:已禁用(丢失) 5:已停用(回收).
*/
public Integer getPosState() {
return posState;
}
/**
* 设置 机具状态: 1:正常 2:故障 3:维修中(返厂) 4:已禁用(丢失) 5:已停用(回收).
*
* @param posState 机具状态: 1:正常 2:故障 3:维修中(返厂) 4:已禁用(丢失) 5:已停用(回收).
*/
public void setPosState(Integer posState) {
this.posState = posState;
}
/**
* 获取 创建时间.
*
* @return 创建时间.
*/
public Date getCreatedTime() {
return createdTime;
}
/**
* 设置 创建时间.
*
* @param createdTime 创建时间.
*/
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
/**
* 获取 更新时间.
*
* @return 更新时间.
*/
public Date getUpdatedTime() {
return updatedTime;
}
/**
* 设置 更新时间.
*
* @param updatedTime 更新时间.
*/
public void setUpdatedTime(Date updatedTime) {
this.updatedTime = updatedTime;
}
protected Serializable pkVal() {
return this.id;
}
}

View File

@ -0,0 +1,176 @@
package com.xncoding.jwt.common.dao.entity;
import java.io.Serializable;
import java.util.Date;
/**
* POS机历史归属表
*
* @author 熊能
* @version 1.0
* @since 2018/01/02
*/
public class PosHistory {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Integer id;
/**
* POS机ID
*/
private Integer posId;
/**
* 归属网点
*/
private String location;
/**
* 绑定时间
*/
private Date bindtime;
/**
* 解绑时间
*/
private Date unbindtime;
/**
* 创建时间
*/
private Date createdTime;
/**
* 更新时间
*/
private Date updatedTime;
/**
* 获取 主键ID.
*
* @return 主键ID.
*/
public Integer getId() {
return id;
}
/**
* 设置 主键ID.
*
* @param id 主键ID.
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取 POS机ID.
*
* @return POS机ID.
*/
public Integer getPosId() {
return posId;
}
/**
* 设置 POS机ID.
*
* @param posId POS机ID.
*/
public void setPosId(Integer posId) {
this.posId = posId;
}
/**
* 获取 归属网点.
*
* @return 归属网点.
*/
public String getLocation() {
return location;
}
/**
* 设置 归属网点.
*
* @param location 归属网点.
*/
public void setLocation(String location) {
this.location = location;
}
/**
* 获取 绑定时间.
*
* @return 绑定时间.
*/
public Date getBindtime() {
return bindtime;
}
/**
* 设置 绑定时间.
*
* @param bindtime 绑定时间.
*/
public void setBindtime(Date bindtime) {
this.bindtime = bindtime;
}
/**
* 获取 解绑时间.
*
* @return 解绑时间.
*/
public Date getUnbindtime() {
return unbindtime;
}
/**
* 设置 解绑时间.
*
* @param unbindtime 解绑时间.
*/
public void setUnbindtime(Date unbindtime) {
this.unbindtime = unbindtime;
}
/**
* 获取 创建时间.
*
* @return 创建时间.
*/
public Date getCreatedTime() {
return createdTime;
}
/**
* 设置 创建时间.
*
* @param createdTime 创建时间.
*/
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
/**
* 获取 更新时间.
*
* @return 更新时间.
*/
public Date getUpdatedTime() {
return updatedTime;
}
/**
* 设置 更新时间.
*
* @param updatedTime 更新时间.
*/
public void setUpdatedTime(Date updatedTime) {
this.updatedTime = updatedTime;
}
protected Serializable pkVal() {
return this.id;
}
}

View File

@ -0,0 +1,198 @@
package com.xncoding.jwt.common.dao.entity;
import java.io.Serializable;
import java.util.Date;
/**
* POS机监控表
*
* @author 熊能
* @version 1.0
* @since 2018/01/02
*/
public class PosMonitor {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Integer id;
/**
* POS机ID
*/
private Integer posId;
/**
* Socket会话ID
*/
private String sessionId;
/**
* 最近一次报告时间
*/
private Date reportTime;
/**
* 最近一次报告地址
*/
private String reportLocation;
/**
* 在线状态: 1:在线 2:离线
*/
private Integer onlineState;
/**
* 创建时间
*/
private Date createdTime;
/**
* 更新时间
*/
private Date updatedTime;
/**
* 获取 主键ID.
*
* @return 主键ID.
*/
public Integer getId() {
return id;
}
/**
* 设置 主键ID.
*
* @param id 主键ID.
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取 POS机ID.
*
* @return POS机ID.
*/
public Integer getPosId() {
return posId;
}
/**
* 设置 POS机ID.
*
* @param posId POS机ID.
*/
public void setPosId(Integer posId) {
this.posId = posId;
}
/**
* 获取 Socket会话ID.
*
* @return Socket会话ID.
*/
public String getSessionId() {
return sessionId;
}
/**
* 设置 Socket会话ID.
*
* @param sessionId Socket会话ID.
*/
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
/**
* 获取 最近一次报告时间.
*
* @return 最近一次报告时间.
*/
public Date getReportTime() {
return reportTime;
}
/**
* 设置 最近一次报告时间.
*
* @param reportTime 最近一次报告时间.
*/
public void setReportTime(Date reportTime) {
this.reportTime = reportTime;
}
/**
* 获取 最近一次报告地址.
*
* @return 最近一次报告地址.
*/
public String getReportLocation() {
return reportLocation;
}
/**
* 设置 最近一次报告地址.
*
* @param reportLocation 最近一次报告地址.
*/
public void setReportLocation(String reportLocation) {
this.reportLocation = reportLocation;
}
/**
* 获取 在线状态: 1:在线 2:离线.
*
* @return 在线状态: 1:在线 2:离线.
*/
public Integer getOnlineState() {
return onlineState;
}
/**
* 设置 在线状态: 1:在线 2:离线.
*
* @param onlineState 在线状态: 1:在线 2:离线.
*/
public void setOnlineState(Integer onlineState) {
this.onlineState = onlineState;
}
/**
* 获取 创建时间.
*
* @return 创建时间.
*/
public Date getCreatedTime() {
return createdTime;
}
/**
* 设置 创建时间.
*
* @param createdTime 创建时间.
*/
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
/**
* 获取 更新时间.
*
* @return 更新时间.
*/
public Date getUpdatedTime() {
return updatedTime;
}
/**
* 设置 更新时间.
*
* @param updatedTime 更新时间.
*/
public void setUpdatedTime(Date updatedTime) {
this.updatedTime = updatedTime;
}
protected Serializable pkVal() {
return this.id;
}
}

View File

@ -0,0 +1,154 @@
package com.xncoding.jwt.common.dao.entity;
import java.io.Serializable;
import java.util.Date;
/**
* 项目表
*
* @author 熊能
* @version 1.0
* @since 2018/01/02
*/
public class Project {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Integer id;
/**
* 项目名称
*/
private String name;
/**
* 应用编号
*/
private String applicationId;
/**
* 项目图片
*/
private String icon;
/**
* 创建时间
*/
private Date createdTime;
/**
* 更新时间
*/
private Date updatedTime;
/**
* 获取 主键ID.
*
* @return 主键ID.
*/
public Integer getId() {
return id;
}
/**
* 设置 主键ID.
*
* @param id 主键ID.
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取 项目名称.
*
* @return 项目名称.
*/
public String getName() {
return name;
}
/**
* 设置 项目名称.
*
* @param name 项目名称.
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取 应用编号.
*
* @return 应用编号.
*/
public String getApplicationId() {
return applicationId;
}
/**
* 设置 应用编号.
*
* @param applicationId 应用编号.
*/
public void setApplicationId(String applicationId) {
this.applicationId = applicationId;
}
/**
* 获取 项目图片.
*
* @return 项目图片.
*/
public String getIcon() {
return icon;
}
/**
* 设置 项目图片.
*
* @param icon 项目图片.
*/
public void setIcon(String icon) {
this.icon = icon;
}
/**
* 获取 创建时间.
*
* @return 创建时间.
*/
public Date getCreatedTime() {
return createdTime;
}
/**
* 设置 创建时间.
*
* @param createdTime 创建时间.
*/
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
/**
* 获取 更新时间.
*
* @return 更新时间.
*/
public Date getUpdatedTime() {
return updatedTime;
}
/**
* 设置 更新时间.
*
* @param updatedTime 更新时间.
*/
public void setUpdatedTime(Date updatedTime) {
this.updatedTime = updatedTime;
}
protected Serializable pkVal() {
return this.id;
}
}

View File

@ -0,0 +1,132 @@
package com.xncoding.jwt.common.dao.entity;
import java.io.Serializable;
import java.util.Date;
/**
* 项目用户关联表
*
* @author 熊能
* @version 1.0
* @since 2018/01/02
*/
public class ProjectUser {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Integer id;
/**
* 用户ID
*/
private Integer userId;
/**
* 项目ID
*/
private Integer projectId;
/**
* 创建时间
*/
private Date createdTime;
/**
* 更新时间
*/
private Date updatedTime;
/**
* 获取 主键ID.
*
* @return 主键ID.
*/
public Integer getId() {
return id;
}
/**
* 设置 主键ID.
*
* @param id 主键ID.
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取 用户ID.
*
* @return 用户ID.
*/
public Integer getUserId() {
return userId;
}
/**
* 设置 用户ID.
*
* @param userId 用户ID.
*/
public void setUserId(Integer userId) {
this.userId = userId;
}
/**
* 获取 项目ID.
*
* @return 项目ID.
*/
public Integer getProjectId() {
return projectId;
}
/**
* 设置 项目ID.
*
* @param projectId 项目ID.
*/
public void setProjectId(Integer projectId) {
this.projectId = projectId;
}
/**
* 获取 创建时间.
*
* @return 创建时间.
*/
public Date getCreatedTime() {
return createdTime;
}
/**
* 设置 创建时间.
*
* @param createdTime 创建时间.
*/
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
/**
* 获取 更新时间.
*
* @return 更新时间.
*/
public Date getUpdatedTime() {
return updatedTime;
}
/**
* 设置 更新时间.
*
* @param updatedTime 更新时间.
*/
public void setUpdatedTime(Date updatedTime) {
this.updatedTime = updatedTime;
}
protected Serializable pkVal() {
return this.id;
}
}

View File

@ -0,0 +1,132 @@
package com.xncoding.jwt.common.dao.entity;
import java.io.Serializable;
import java.util.Date;
/**
* 角色表
*
* @author 熊能
* @version 1.0
* @since 2018/01/02
*/
public class Role {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Integer id;
/**
* 角色名称
*/
private String role;
/**
* 角色说明
*/
private String description;
/**
* 创建时间
*/
private Date createdTime;
/**
* 更新时间
*/
private Date updatedTime;
/**
* 获取 主键ID.
*
* @return 主键ID.
*/
public Integer getId() {
return id;
}
/**
* 设置 主键ID.
*
* @param id 主键ID.
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取 角色名称.
*
* @return 角色名称.
*/
public String getRole() {
return role;
}
/**
* 设置 角色名称.
*
* @param role 角色名称.
*/
public void setRole(String role) {
this.role = role;
}
/**
* 获取 角色说明.
*
* @return 角色说明.
*/
public String getDescription() {
return description;
}
/**
* 设置 角色说明.
*
* @param description 角色说明.
*/
public void setDescription(String description) {
this.description = description;
}
/**
* 获取 创建时间.
*
* @return 创建时间.
*/
public Date getCreatedTime() {
return createdTime;
}
/**
* 设置 创建时间.
*
* @param createdTime 创建时间.
*/
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
/**
* 获取 更新时间.
*
* @return 更新时间.
*/
public Date getUpdatedTime() {
return updatedTime;
}
/**
* 设置 更新时间.
*
* @param updatedTime 更新时间.
*/
public void setUpdatedTime(Date updatedTime) {
this.updatedTime = updatedTime;
}
protected Serializable pkVal() {
return this.id;
}
}

View File

@ -0,0 +1,132 @@
package com.xncoding.jwt.common.dao.entity;
import java.io.Serializable;
import java.util.Date;
/**
* 角色权限关联表
*
* @author 熊能
* @version 1.0
* @since 2018/01/02
*/
public class RolePermission {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Integer id;
/**
* 角色ID
*/
private Integer roleId;
/**
* 权限ID
*/
private Integer permissionId;
/**
* 创建时间
*/
private Date createdTime;
/**
* 更新时间
*/
private Date updatedTime;
/**
* 获取 主键ID.
*
* @return 主键ID.
*/
public Integer getId() {
return id;
}
/**
* 设置 主键ID.
*
* @param id 主键ID.
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取 角色ID.
*
* @return 角色ID.
*/
public Integer getRoleId() {
return roleId;
}
/**
* 设置 角色ID.
*
* @param roleId 角色ID.
*/
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
/**
* 获取 权限ID.
*
* @return 权限ID.
*/
public Integer getPermissionId() {
return permissionId;
}
/**
* 设置 权限ID.
*
* @param permissionId 权限ID.
*/
public void setPermissionId(Integer permissionId) {
this.permissionId = permissionId;
}
/**
* 获取 创建时间.
*
* @return 创建时间.
*/
public Date getCreatedTime() {
return createdTime;
}
/**
* 设置 创建时间.
*
* @param createdTime 创建时间.
*/
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
/**
* 获取 更新时间.
*
* @return 更新时间.
*/
public Date getUpdatedTime() {
return updatedTime;
}
/**
* 设置 更新时间.
*
* @param updatedTime 更新时间.
*/
public void setUpdatedTime(Date updatedTime) {
this.updatedTime = updatedTime;
}
protected Serializable pkVal() {
return this.id;
}
}

View File

@ -0,0 +1,41 @@
package com.xncoding.jwt.common.util;
/**
* 常用工具类字符串数字相关
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/15
*/
public class CommonUtil {
/**
* 检查某版本是否比现在版本更大些
*
* @param version 某版本
* @param nowVersion 现在使用的版本
* @return 是否版本数更大
*/
public static boolean isNewer(String version, String nowVersion) {
try {
String[] versions = version.split("\\.");
String[] nowVersions = nowVersion.split("\\.");
if (versions.length != nowVersions.length) {
return false;
}
int sum = 0;
for (String v : versions) {
sum += sum * 10 + Integer.valueOf(v);
}
int nowSum = 0;
for (String nv : nowVersions) {
nowSum += nowSum * 10 + Integer.valueOf(nv);
}
return sum > nowSum;
} catch (NumberFormatException e) {
return false;
}
}
}

View File

@ -0,0 +1,296 @@
/**
* Copyright (c) 2015-2016, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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 com.xncoding.jwt.common.util;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class DateUtil {
private final static SimpleDateFormat sdfYear = new SimpleDateFormat("yyyy");
private final static SimpleDateFormat sdfDay = new SimpleDateFormat("yyyy-MM-dd");
private final static SimpleDateFormat sdfDays = new SimpleDateFormat("yyyyMMdd");
private final static SimpleDateFormat sdfTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private final static SimpleDateFormat sdfmsTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
private final static SimpleDateFormat allTime = new SimpleDateFormat("yyyyMMddHHmmss");
private final static SimpleDateFormat sdfDay_ = new SimpleDateFormat("yyyy/MM/dd");
/**
* 获取YYYY格式
*
* @return
*/
public static String getYear() {
return sdfYear.format(new Date());
}
/**
* 获取YYYY格式
*
* @return
*/
public static String getYear(Date date) {
return sdfYear.format(date);
}
/**
* 获取YYYY-MM-DD格式
*
* @return
*/
public static String getDay() {
return sdfDay.format(new Date());
}
/**
* 获取YYYY-MM-DD格式
*
* @return
*/
public static String getDay(Date date) {
return sdfDay.format(date);
}
/**
* 获取YYYYMMDD格式
*
* @return
*/
public static String getDays() {
return sdfDays.format(new Date());
}
/**
* 获取YYYYMMDD格式
*
* @return
*/
public static String getDays(Date date) {
return sdfDays.format(date);
}
/**
* 获取YYYY/MM/DD格式
*
* @return
*/
public static String getDays_(Date date) {
return sdfDay_.format(date);
}
/**
* 获取YYYY-MM-DD HH:mm:ss格式
*
* @return
*/
public static String getTime() {
return sdfTime.format(new Date());
}
/**
* 获取YYYY-MM-DD HH:mm:ss.SSS格式
*
* @return
*/
public static String getMsTime() {
return sdfmsTime.format(new Date());
}
/**
* 获取YYYYMMDDHHmmss格式
*
* @return
*/
public static String getAllTime() {
return allTime.format(new Date());
}
/**
* 获取YYYY-MM-DD HH:mm:ss格式
*
* @return
*/
public static String getTime(Date date) {
return sdfTime.format(date);
}
/**
* @param s
* @param e
* @return boolean
* @throws
* @Title: compareDate
* @Description:(日期比较如果s>=e 返回true 否则返回false)
* @author luguosui
*/
public static boolean compareDate(String s, String e) {
if (parseDate(s) == null || parseDate(e) == null) {
return false;
}
return parseDate(s).getTime() >= parseDate(e).getTime();
}
/**
* 格式化日期
*
* @return
*/
public static Date parseDate(String date) {
try {
return sdfDay.parse(date);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
/**
* 格式化日期
*
* @return
*/
public static Date parseTime(String date) {
try {
return sdfTime.parse(date);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
/**
* 格式化日期
*
* @return
*/
public static Date parse(String date, String pattern) {
DateFormat fmt = new SimpleDateFormat(pattern);
try {
return fmt.parse(date);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
/**
* 格式化日期
*
* @return
*/
public static String format(Date date, String pattern) {
DateFormat fmt = new SimpleDateFormat(pattern);
return fmt.format(date);
}
/**
* 把日期转换为Timestamp
*
* @param date
* @return
*/
public static Timestamp format(Date date) {
return new Timestamp(date.getTime());
}
/**
* 校验日期是否合法
*
* @return
*/
public static boolean isValidDate(String s) {
try {
sdfTime.parse(s);
return true;
} catch (Exception e) {
// 如果throw java.text.ParseException或者NullPointerException就说明格式不对
return false;
}
}
/**
* 校验日期是否合法
*
* @return
*/
public static boolean isValidDate(String s, String pattern) {
DateFormat fmt = new SimpleDateFormat(pattern);
try {
fmt.parse(s);
return true;
} catch (Exception e) {
// 如果throw java.text.ParseException或者NullPointerException就说明格式不对
return false;
}
}
/**
* 获取指定日期偏移指定时间后的时间
*
* @param date 基准日期
* @param calendarField 偏移的粒度大小小时月等使用Calendar中的常数
* @param offsite 偏移量正数为向后偏移负数为向前偏移
* @return 偏移后的日期
*/
public static Date offsiteDate(Date date, int calendarField, int offsite) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(calendarField, offsite);
return cal.getTime();
}
/**
* 返回日期零时
*
* @param date 目标日期
* @return 目标日期零时
*/
public static Date getDateStartTime(Date date) {
String str = format(date, "yyyyMMdd") + "000000";
try {
return allTime.parse(str);
} catch (ParseException e) {
return null;
}
}
/**
* 返回日期最后时间End
*
* @param date 目标日期
* @return 目标日日期最后时间
*/
public static Date getDateEndTime(Date date) {
String str = format(date, "yyyyMMdd") + "235959";
try {
return allTime.parse(str);
} catch (ParseException e) {
return null;
}
}
}

View File

@ -0,0 +1,173 @@
package com.xncoding.jwt.common.util;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.UnsupportedEncodingException;
import java.util.Date;
public class JWTUtil {
private static final Logger log = LoggerFactory.getLogger(JWTUtil.class);
// 过期时间5分钟
private static final long EXPIRE_TIME = 5 * 60 * 1000;
/**
* 校验token是否正确
*
* @param token 密钥
* @param secret 用户的密码
* @return 是否正确
*/
public static boolean verify(String token, String username, String secret) {
try {
Algorithm algorithm = Algorithm.HMAC256(secret);
JWTVerifier verifier = JWT.require(algorithm)
.withClaim("username", username)
.build();
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception exception) {
log.error("校验token失败", exception);
return false;
}
}
/**
* 获得token中的信息无需secret解密也能获得
*
* @return token中包含的用户名
*/
public static String getUsername(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("username").asString();
} catch (JWTDecodeException e) {
return null;
}
}
/**
* 生成签名,5min后过期
*
* @param username 用户名
* @param secret 用户的密码
* @return 加密的token
*/
public static String sign(String username, String secret) {
try {
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
Algorithm algorithm = Algorithm.HMAC256(secret);
// 附带username信息
return JWT.create()
.withClaim("username", username)
.withExpiresAt(date)
.sign(algorithm);
} catch (UnsupportedEncodingException e) {
return null;
}
}
/*----------------------------以下是socket校验--------------------------*/
/**
* 生成Socket Token签名, 5min后过期
*
* @param username 用户名
* @param secret 用户的密码
* @param appid applicationId
* @param imei IMEI码
* @return 加密的token
*/
public static String signSocket(String username, String secret, String appid, String imei) {
try {
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
Algorithm algorithm = Algorithm.HMAC256(secret);
// 附带username信息
return JWT.create()
.withClaim("username", username)
.withClaim("appid", appid)
.withClaim("imei", imei)
.withExpiresAt(date)
.sign(algorithm);
} catch (UnsupportedEncodingException e) {
return null;
}
}
/**
* 校验token是否正确
*
* @param token 密钥
* @param secret 用户的密码
* @return 是否正确
*/
public static boolean verifySocket(String token, String secret) {
try {
DecodedJWT jwt1 = JWT.decode(token);
String username = jwt1.getClaim("username").asString();
String appid = jwt1.getClaim("appid").asString();
String imei = jwt1.getClaim("imei").asString();
Algorithm algorithm = Algorithm.HMAC256(secret);
JWTVerifier verifier = JWT.require(algorithm)
.withClaim("username", username)
.withClaim("appid", appid)
.withClaim("imei", imei)
.build();
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception exception) {
log.error("校验token失败", exception);
return false;
}
}
/**
* 获得token中的信息无需secret解密也能获得
*
* @return token中包含的用户名
*/
public static String getSocketUsername(String token) {
try {
DecodedJWT jwt1 = JWT.decode(token);
return jwt1.getClaim("username").asString();
} catch (JWTDecodeException e) {
return null;
}
}
/**
* 获得token中的信息无需secret解密也能获得
*
* @return token中包含的Appid
*/
public static String getSocketAppid(String token) {
try {
DecodedJWT jwt1 = JWT.decode(token);
return jwt1.getClaim("appid").asString();
} catch (JWTDecodeException e) {
return null;
}
}
/**
* 获得token中的信息无需secret解密也能获得
*
* @return token中包含的IMEI码
*/
public static String getSocketImei(String token) {
try {
DecodedJWT jwt1 = JWT.decode(token);
return jwt1.getClaim("imei").asString();
} catch (JWTDecodeException e) {
return null;
}
}
}

View File

@ -0,0 +1,134 @@
package com.xncoding.jwt.config;
import com.xncoding.jwt.shiro.JWTFilter;
import com.xncoding.jwt.shiro.MyShiroRealm;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Description : Apache Shiro 核心通过 Filter 来实现就好像SpringMvc 通过DispachServlet 来主控制一样
* 既然是使用 Filter 一般也就能猜到是通过URL规则来进行过滤和权限校验所以我们需要定义一系列关于URL的规则和访问权限
*/
@Configuration
@Order(1)
public class ShiroConfig {
/**
* ShiroFilterFactoryBean 处理拦截资源文件问题
* 注意单独一个ShiroFilterFactoryBean配置是或报错的以为在
* 初始化ShiroFilterFactoryBean的时候需要注入SecurityManager Filter Chain定义说明
* 1一个URL可以配置多个Filter使用逗号分隔
* 2当设置多个过滤器时全部验证通过才视为通过
* 3部分过滤器可指定参数如permsroles
*/
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
//验证码过滤器
Map<String, Filter> filtersMap = shiroFilterFactoryBean.getFilters();
filtersMap.put("jwt", new JWTFilter());
shiroFilterFactoryBean.setFilters(filtersMap);
// 拦截器
//rest比如/admins/user/**=rest[user],根据请求的方法相当于/admins/user/**=perms[usermethod] ,其中method为postgetdelete等
//port比如/admins/user/**=port[8081],当请求的url的端口不是8081是跳转到schemal//serverName8081?queryString,其中schmal是协议http或https等serverName是你访问的host,8081是url配置里port的端口queryString是你访问的url里的后面的参数
//perms比如/admins/user/**=perms[useradd*],perms参数可以写多个多个时必须加上引号并且参数之间用逗号分割比如/admins/user/**=perms["useradd*,usermodify*"]当有多个参数时必须每个参数都通过才通过想当于isPermitedAll()方法
//roles比如/admins/user/**=roles[admin],参数可以写多个多个时必须加上引号并且参数之间用逗号分割当有多个参数时比如/admins/user/**=roles["admin,guest"],每个参数通过才算通过相当于hasAllRoles()方法//要实现or的效果看http://zgzty.blog.163.com/blog/static/83831226201302983358670/
//anon比如/admins/**=anon 没有参数表示可以匿名使用
//authc比如/admins/user/**=authc表示需要认证才能使用没有参数
//authcBasic比如/admins/user/**=authcBasic没有参数表示httpBasic认证
//ssl比如/admins/user/**=ssl没有参数表示安全的url请求协议为https
//user比如/admins/user/**=user没有参数表示必须存在用户当登入操作时不做检查
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
// swagger接口文档
filterChainDefinitionMap.put("/v2/api-docs", "anon");
filterChainDefinitionMap.put("/webjars/**", "anon");
filterChainDefinitionMap.put("/swagger-resources/**", "anon");
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
filterChainDefinitionMap.put("/doc.html", "anon");
// 其他的
filterChainDefinitionMap.put("/**", "jwt");
// 访问401和404页面不通过我们的Filter
filterChainDefinitionMap.put("/401", "anon");
filterChainDefinitionMap.put("/404", "anon");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
securityManager.setRealm(myShiroRealm());
//注入缓存管理器
securityManager.setCacheManager(ehCacheManager());
/*
* 关闭shiro自带的session详情见文档
* http://shiro.apache.org/session-management.html#SessionManagement-StatelessApplications%28Sessionless%29
*/
DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
securityManager.setSubjectDAO(subjectDAO);
return securityManager;
}
/**
* 身份认证realm; (这个需要自己写账号密码校验权限等)
*/
@Bean
public MyShiroRealm myShiroRealm() {
MyShiroRealm myShiroRealm = new MyShiroRealm();
return myShiroRealm;
}
/**
* 开启shiro aop注解支持. 使用代理方式; 所以需要开启代码支持;
*
* @param securityManager 安全管理器
* @return 授权Advisor
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
/**
* shiro缓存管理器;
* 需要注入对应的其它的实体类中
* 1安全管理器securityManager
* 可见securityManager是整个shiro的核心
*
* @return
*/
@Bean
public EhCacheManager ehCacheManager() {
EhCacheManager cacheManager = new EhCacheManager();
cacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
return cacheManager;
}
}

View File

@ -0,0 +1,97 @@
package com.xncoding.jwt.dao.entity;
import com.xncoding.jwt.common.constant.DictMap;
import com.xncoding.jwt.common.dao.entity.Manager;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
/**
* Description: 后台运维管理员信息
*/
public class ManagerInfo extends Manager implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 状态
*/
private String stateStr;
/**
* 所属项目id列表逗号分隔
*/
private String pids;
/**
* 所属项目名列表逗号分隔
*/
private String pnames;
/**
* 所属项目id列表
*/
private List<Integer> pidsList;
/**
* 一个管理员具有多个角色
*/
private List<SysRole> roles;// 一个用户具有多个角色
public ManagerInfo() {
}
public List<SysRole> getRoles() {
return roles;
}
public void setRoles(List<SysRole> roles) {
this.roles = roles;
}
/**
* 密码盐
*/
public String getCredentialsSalt() {
return getUsername() + getSalt();
}
@Override
public String toString() {
return "username:" + getUsername() + "|name=" + getName();
}
public String getStateStr() {
return stateStr;
}
public void setStateStr(String stateStr) {
this.stateStr = stateStr;
}
public String getPids() {
return pids;
}
public void setPids(String pids) {
this.pids = pids;
}
public List<Integer> getPidsList() {
return pidsList;
}
public void setPidsList(List<Integer> pidsList) {
this.pidsList = pidsList;
}
public String getPnames() {
return pnames;
}
public void setPnames(String pnames) {
this.pnames = pnames;
}
public void buildTable() {
stateStr = DictMap.value(DictMap.KEY_USER_STATUS, getState());
}
}

View File

@ -0,0 +1,29 @@
package com.xncoding.jwt.dao.entity;
import com.xncoding.jwt.common.dao.entity.Permission;
import com.xncoding.jwt.common.dao.entity.Role;
import java.io.Serializable;
import java.util.List;
/**
* Description : 角色信息
*/
public class SysRole extends Role implements Serializable {
private static final long serialVersionUID = 1L;
// 拥有的权限列表
private List<Permission> permissions;
public SysRole() {
}
public List<Permission> getPermissions() {
return permissions;
}
public void setPermissions(List<Permission> permissions) {
this.permissions = permissions;
}
}

View File

@ -0,0 +1,14 @@
package com.xncoding.jwt.exception;
import org.apache.shiro.authc.AuthenticationException;
/**
* 禁用用户异常
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/12
*/
public class ForbiddenUserException extends AuthenticationException {
}

View File

@ -0,0 +1,18 @@
package com.xncoding.jwt.exception;
/**
* UnauthorizedException
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/22
*/
public class UnauthorizedException extends RuntimeException {
public UnauthorizedException(String msg) {
super(msg);
}
public UnauthorizedException() {
super();
}
}

View File

@ -0,0 +1,146 @@
package com.xncoding.jwt.service;
import com.xncoding.jwt.api.model.ReportParam;
import com.xncoding.jwt.api.model.VersionParam;
import com.xncoding.jwt.api.model.VersionResult;
import com.xncoding.jwt.common.dao.entity.Pos;
import com.xncoding.jwt.common.dao.entity.Project;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
/**
* 专门用来服务对外接口用Service
*/
@Service
public class ApiService {
private static final Logger logger = LoggerFactory.getLogger(ApiService.class);
/**
* 根据IMEI码查询POS机是否已经入网
*
* @param imei IMEI码
* @return 数量
*/
public int selectCount(String imei) {
return 1;
}
/**
* 根据IMEI码查找POS
*
* @param imei
* @return
*/
public Pos selectByImei(String imei) {
Pos p = new Pos();
p.setImei(imei);
return p;
}
/**
* 根据IMEI码查找绑定网点的POS
*
* @param imei
* @return
*/
public Pos selectBindByImei(String imei) {
return null;
}
/**
* 根据IMEI码查询POS机是否绑定了网点
*
* @param imei IMEI码
* @return 绑定数量
*/
public int selectBindCount(String imei) {
return 1;
}
/**
* 更新机具信息
*
* @param pos
* @return
*/
public int bindLocation(Pos pos) {
return 1;
}
/**
* 执行POS机入网
*
* @param param 参数
* @return 结果
*/
public int insertPos(Pos param) {
return 1;
}
/**
* 根据Application Id查询项目
*
* @param applicationId Application Id
* @return 项目
*/
public Project selectProjectByApplicationId(String applicationId) {
Project p = new Project();
return p;
}
/**
* 更新报告
*
* @param param 报告参数
* @return 结果
*/
public int report(ReportParam param) {
return 1;
}
/**
* Just Update monitor state
*
* @param param report param
* @param sessionId session id.
* @param state 1:在线 2:离线.
* @return result
*/
public int updateJustState(ReportParam param, String sessionId, Integer state) {
return 1;
}
/**
* 根据imei码获取session id
*
* @param imei imei码
* @return sessionId
*/
public String selectSessionId(String imei) {
return "11";
}
/**
* 查询版本发布
* @param param 查询版本参数
* @return 结果
*/
public VersionResult selectPublishCount(VersionParam param) {
return new VersionResult();
}
/**
* 给某个POS机推送网点解除绑定消息
* @param imei imei码
* @param location 解除的网点
* @return error msg
*/
public String sendUnbind(String imei, String location) {
logger.info("开始给POS机推送解绑消息");
return null;
}
}

View File

@ -0,0 +1,45 @@
package com.xncoding.jwt.service;
import com.xncoding.jwt.dao.entity.ManagerInfo;
import com.xncoding.jwt.dao.entity.SysRole;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
* 后台用户管理
*/
@Service
public class ManagerInfoService {
/**
* 通过名称查找用户
*
* @param username
* @return
*/
public ManagerInfo findByUsername(String username) {
ManagerInfo managerInfo = new ManagerInfo();
managerInfo.setPids("1,2,3");
managerInfo.setPidsList(Arrays.asList(1, 2, 3));
managerInfo.setPnames("第1个,第2个");
managerInfo.setState(1);
managerInfo.setCreatedTime(new Date());
managerInfo.setName("系统管理员");
managerInfo.setPassword("4a496ba2a4172c71540fa643ddc8bb7c");
managerInfo.setSalt("b4752b4b73034de06afb2db30fe19061");
List<SysRole> roles = new ArrayList<>();
SysRole role = new SysRole();
role.setId(1);
role.setRole("admin");
role.setDescription("超级管理员");
roles.add(role);
managerInfo.setRoles(roles);
return managerInfo;
}
}

View File

@ -0,0 +1,94 @@
package com.xncoding.jwt.shiro;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class JWTFilter extends BasicHttpAuthenticationFilter {
private Logger LOGGER = LoggerFactory.getLogger(this.getClass());
/**
* 判断用户是否想要登入
* 检测header里面是否包含Authorization字段即可
*/
@Override
protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
HttpServletRequest req = (HttpServletRequest) request;
String authorization = req.getHeader("Authorization");
return authorization != null;
}
/**
*
*/
@Override
protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String authorization = httpServletRequest.getHeader("Authorization");
JWTToken token = new JWTToken(authorization);
// 提交给realm进行登入如果错误他会抛出异常并被捕获
getSubject(request, response).login(token);
// 如果没有抛出异常则代表登入成功返回true
return true;
}
/**
* 这里我们详细说明下为什么最终返回的都是true即允许访问
* 例如我们提供一个地址 GET /article
* 登入用户和游客看到的内容是不同的
* 如果在这里返回了false请求会被直接拦截用户看不到任何东西
* 所以我们在这里返回trueController中可以通过 subject.isAuthenticated() 来判断用户是否登入
* 如果有些资源只有登入用户才能访问我们只需要在方法上面加上 @RequiresAuthentication 注解即可
* 但是这样做有一个缺点就是不能够对GET,POST等请求进行分别过滤鉴权(因为我们重写了官方的方法)但实际上对应用影响不大
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
if (isLoginAttempt(request, response)) {
try {
executeLogin(request, response);
} catch (Exception e) {
response401(request, response);
}
}
return true;
}
/**
* 对跨域提供支持
*/
@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));
httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
// 跨域时会首先发送一个option请求这里我们给option请求直接返回正常状态
if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
httpServletResponse.setStatus(HttpStatus.OK.value());
return false;
}
return super.preHandle(request, response);
}
/**
* 将非法请求跳转到 /401
*/
private void response401(ServletRequest req, ServletResponse resp) {
try {
HttpServletResponse httpServletResponse = (HttpServletResponse) resp;
httpServletResponse.sendRedirect("/401");
} catch (IOException e) {
LOGGER.error(e.getMessage());
}
}
}

View File

@ -0,0 +1,23 @@
package com.xncoding.jwt.shiro;
import org.apache.shiro.authc.AuthenticationToken;
public class JWTToken implements AuthenticationToken {
// 密钥
private String token;
public JWTToken(String token) {
this.token = token;
}
@Override
public Object getPrincipal() {
return token;
}
@Override
public Object getCredentials() {
return token;
}
}

View File

@ -0,0 +1,121 @@
package com.xncoding.jwt.shiro;
import com.xncoding.jwt.common.dao.entity.Permission;
import com.xncoding.jwt.common.util.JWTUtil;
import com.xncoding.jwt.dao.entity.ManagerInfo;
import com.xncoding.jwt.dao.entity.SysRole;
import com.xncoding.jwt.service.ManagerInfoService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Description : 身份校验核心类
*/
public class MyShiroRealm extends AuthorizingRealm {
private static final Logger _logger = LoggerFactory.getLogger(MyShiroRealm.class);
@Autowired
ManagerInfoService managerInfoService;
/**
* JWT签名密钥
*/
public static final String SECRET = "9281e268b77b7c439a20b46fd1483b9a";
/**
* 必须重写此方法不然Shiro会报错
*/
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof JWTToken;
}
/**
* 认证信息(身份验证)
* Authentication 是用来验证用户身份
*
* @param auth
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth)
throws AuthenticationException {
_logger.info("MyShiroRealm.doGetAuthenticationInfo()");
String token = (String) auth.getCredentials();
// 解密获得username用于和数据库进行对比
String username = JWTUtil.getUsername(token);
if (username == null) {
throw new AuthenticationException("token invalid");
}
//通过username从数据库中查找 ManagerInfo对象
//实际项目中这里可以根据实际情况做缓存如果不做Shiro自己也是有时间间隔机制2分钟内不会重复执行该方法
ManagerInfo managerInfo = managerInfoService.findByUsername(username);
if (managerInfo == null) {
throw new AuthenticationException("用户不存在!");
}
if (!JWTUtil.verify(token, username, managerInfo.getPassword())) {
throw new AuthenticationException("Token认证失败");
}
return new SimpleAuthenticationInfo(token, token, "my_realm");
}
/**
* 此方法调用hasRole,hasPermission的时候才会进行回调.
* <p>
* 权限信息.(授权):
* 1如果用户正常退出缓存自动清空
* 2如果用户非正常退出缓存自动清空
* 3如果我们修改了用户的权限而用户不退出系统修改的权限无法立即生效
* 需要手动编程进行实现放在service进行调用
* 在权限修改后调用realm中的方法realm已经由spring管理所以从spring中获取realm实例调用clearCached方法
* :Authorization 是授权访问控制用于对用户进行的操作授权证明该用户是否允许进行当前操作如访问某个链接某个资源文件等
*
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
/*
* 当没有使用缓存的时候不断刷新页面的话这个代码会不断执行
* 当其实没有必要每次都重新设置权限信息所以我们需要放到缓存中进行管理
* 当放到缓存中时这样的话doGetAuthorizationInfo就只会执行一次了
* 缓存过期之后会再次执行
*/
_logger.info("权限配置-->MyShiroRealm.doGetAuthorizationInfo()");
String username = JWTUtil.getUsername(principals.toString());
// 下面的可以使用缓存提升速度
ManagerInfo managerInfo = managerInfoService.findByUsername(username);
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//设置相应角色的权限信息
for (SysRole role : managerInfo.getRoles()) {
//设置角色
authorizationInfo.addRole(role.getRole());
for (Permission p : role.getPermissions()) {
//设置权限
authorizationInfo.addStringPermission(p.getPermission());
}
}
return authorizationInfo;
}
}

View File

@ -0,0 +1,187 @@
/**
* Copyright (c) 2015-2017, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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 com.xncoding.jwt.shiro;
import com.xncoding.jwt.dao.entity.ManagerInfo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
/**
* shiro工具类
*
* @author dafei, Chill Zhuang
*/
public class ShiroKit {
private static final String NAMES_DELIMETER = ",";
/**
* 散列算法
*/
public final static String HASH_ALGORITHM_NAME = "MD5";
/**
* 循环次数
*/
public final static int HASH_ITERATIONS = 2;
/**
* shiro密码加密工具类
*
* @param credentials 密码
* @param saltSource 密码盐
* @return
*/
public static String md5(String credentials, String saltSource) {
return new SimpleHash(HASH_ALGORITHM_NAME, credentials, saltSource, HASH_ITERATIONS).toHex();
}
/**
* 获取随机盐值
*
* @param length 字节长度一个字节2位16进制数表示
* @return
*/
public static String getRandomSalt(int length) {
return new SecureRandomNumberGenerator().nextBytes(length).toHex();
}
/**
* 获取当前 Subject
*
* @return Subject
*/
public static Subject getSubject() {
return SecurityUtils.getSubject();
}
/**
* 验证当前用户是否属于该角色,使用时与lacksRole 搭配使用
*
* @param roleName 角色名
* @return 属于该角色true否则false
*/
public static boolean hasRole(String roleName) {
return getSubject() != null && roleName != null
&& roleName.length() > 0 && getSubject().hasRole(roleName);
}
/**
* 与hasRole标签逻辑相反当用户不属于该角色时验证通过
*
* @param roleName 角色名
* @return 不属于该角色true否则false
*/
public static boolean lacksRole(String roleName) {
return !hasRole(roleName);
}
/**
* 验证当前用户是否属于以下任意一个角色
*
* @param roleNames 角色列表
* @return 属于:true,否则false
*/
public static boolean hasAnyRoles(String roleNames) {
boolean hasAnyRole = false;
Subject subject = getSubject();
if (subject != null && roleNames != null && roleNames.length() > 0) {
for (String role : roleNames.split(NAMES_DELIMETER)) {
if (subject.hasRole(role.trim())) {
hasAnyRole = true;
break;
}
}
}
return hasAnyRole;
}
/**
* 验证当前用户是否拥有指定权限,使用时与lacksPermission 搭配使用
*
* @param permission 权限名
* @return 拥有权限true否则false
*/
public static boolean hasPermission(String permission) {
return getSubject() != null && permission != null
&& permission.length() > 0
&& getSubject().isPermitted(permission);
}
/**
* 与hasPermission标签逻辑相反当前用户没有制定权限时验证通过
*
* @param permission 权限名
* @return 拥有权限true否则false
*/
public static boolean lacksPermission(String permission) {
return !hasPermission(permission);
}
/**
* 已认证通过的用户不包含已记住的用户这是与user标签的区别所在与notAuthenticated搭配使用
*
* @return 通过身份验证true否则false
*/
public static boolean isAuthenticated() {
return getSubject() != null && getSubject().isAuthenticated();
}
/**
* 未认证通过用户与authenticated标签相对应与guest标签的区别是该标签包含已记住用户
*
* @return 没有通过身份验证true否则false
*/
public static boolean notAuthenticated() {
return !isAuthenticated();
}
/**
* 认证通过或已记住的用户与guset搭配使用
*
* @return 用户true否则 false
*/
public static boolean isUser() {
return getSubject() != null && getSubject().getPrincipal() != null;
}
/**
* 验证当前用户是否为访客即未认证包含未记住的用户用user搭配使用
*
* @return 访客true否则false
*/
public static boolean isGuest() {
return !isUser();
}
/**
* 输出当前用户信息通常为登录帐号信息
*
* @return 当前用户信息
*/
public static String principal() {
if (getSubject() != null) {
Object principal = getSubject().getPrincipal();
return principal.toString();
}
return "";
}
}

View File

@ -0,0 +1,46 @@
##########################################################
################## 所有profile共有的配置 #################
##########################################################
################### 项目启动端口 ###################
server.port: 9095
################### spring配置 ###################
spring:
profiles:
active: dev
logging:
level:
org.springframework.web.servlet: ERROR
---
#####################################################################
######################## 开发环境profile ##########################
#####################################################################
spring:
profiles: dev
logging:
level:
ROOT: INFO
com:
xncoding: DEBUG
file: E:/logs/pos-api.log
---
#####################################################################
######################## 测试环境profile ##########################
#####################################################################
spring:
profiles: test
logging:
level:
ROOT: INFO
com:
xncoding: DEBUG
file: /var/logs/pos-api.log

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false" monitoring="autodetect"
dynamicConfig="true">
<diskStore path="java.io.tmpdir/ehcache"/>
<defaultCache
maxElementsInMemory="50000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="3600"
overflowToDisk="true"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
/>
<cache name="authorizationCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="3600"
overflowToDisk="false"
statistics="true">
</cache>
<cache name="authenticationCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="3600"
overflowToDisk="false"
statistics="true">
</cache>
<cache name="org.apache.shiro.realm.text.PropertiesRealm-0-accounts"
maxElementsInMemory="1000"
eternal="true"
overflowToDisk="true"/>
</ehcache>
<!--
maxElementsInMemory="10000" //Cache中最多允许保存的数据对象的数量
external="false" //缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期
timeToLiveSeconds="3600" //缓存的存活时间,从开始创建的时间算起
timeToIdleSeconds="3600" //多长时间不访问该缓存那么ehcache 就会清除该缓存
这两个参数很容易误解看文档根本没用我仔细分析了ehcache的代码。结论如下
1、timeToLiveSeconds的定义是以创建时间为基准开始计算的超时时长
2、timeToIdleSeconds的定义是在创建时间和最近访问时间中取出离现在最近的时间作为基准计算的超时时长
3、如果仅设置了timeToLiveSeconds则该对象的超时时间=创建时间+timeToLiveSeconds假设为A
4、如果没设置timeToLiveSeconds则该对象的超时时间=min(创建时间,最近访问时间)+timeToIdleSeconds假设为B
5、如果两者都设置了则取出A、B最少的值即min(A,B),表示只要有一个超时成立即算超时。
overflowToDisk="true" //内存不足时,是否启用磁盘缓存
diskSpoolBufferSizeMB //设置DiskStore磁盘缓存的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区
maxElementsOnDisk //硬盘最大缓存个数
diskPersistent //是否缓存虚拟机重启期数据The default value is false
diskExpiryThreadIntervalSeconds //磁盘失效线程运行时间间隔默认是120秒。
memoryStoreEvictionPolicy="LRU" //当达到maxElementsInMemory限制时Ehcache将会根据指定的策略去清理内存。默认策略是LRU最近最少使用。你可以设置为FIFO先进先出或是LFU较少使用
clearOnFlush //内存数量最大时是否清除
maxEntriesLocalHeap="0"
maxEntriesLocalDisk="1000"
-->

View File

@ -0,0 +1,15 @@
package com.xncoding.jwt;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* 测试密码加密
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {
}

View File

@ -0,0 +1,37 @@
package com.xncoding.jwt;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xncoding.jwt.api.model.VersionParam;
import com.xncoding.jwt.shiro.ShiroKit;
import org.junit.Test;
/**
* SimpleTest
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/4
*/
public class SimpleTest {
@Test
public void testMd5() {
//用户名+随机数
String username = "admin";
String salt = ShiroKit.getRandomSalt(16);
//原密码
String password = "12345678";
String encodedPassword = ShiroKit.md5(password, username + salt);
System.out.println("这个是保存进数据库的密码:" + encodedPassword);
System.out.println("这个是保存进数据库的盐:" + salt);
}
@Test
public void testJackson() throws JsonProcessingException {
VersionParam req = new VersionParam();
String reqBody = new ObjectMapper().writeValueAsString(req);
System.out.println(reqBody);
}
}

View File

@ -0,0 +1,24 @@
package com.xncoding.jwt.common.util;
import org.junit.Test;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class CommonUtilTest {
@Test
public void isNewer() {
assertThat(CommonUtil.isNewer("1.2.1", "1.2.0"), is(true));
assertThat(CommonUtil.isNewer("1.2", "1.2.0"), is(false));
assertThat(CommonUtil.isNewer("2.1.9", "1.2.0"), is(true));
assertThat(CommonUtil.isNewer("adfa.1.3", "1.2.0"), is(false));
}
@Test
public void testTimestamp() {
// 1516072088813
// 1441594722
System.out.println(System.currentTimeMillis());
}
}

Binary file not shown.