From e7f352ade52f83e80fca5a6ba3cae1324f73c079 Mon Sep 17 00:00:00 2001 From: yidao620 Date: Tue, 27 Feb 2018 19:08:19 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BB=A3=E7=A0=81=E7=A4=BA?= =?UTF-8?q?=E4=BE=8Bspringboot-jwt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- springboot-jwt/.gitignore | 17 + springboot-jwt/LICENSE | 20 + springboot-jwt/README.md | 20 + springboot-jwt/pom.xml | 136 +++++++ springboot-jwt/run.sh | 72 ++++ .../java/com/xncoding/jwt/Application.java | 12 + .../xncoding/jwt/api/ExceptionController.java | 48 +++ .../com/xncoding/jwt/api/LoginController.java | 72 ++++ .../xncoding/jwt/api/NotifyController.java | 28 ++ .../xncoding/jwt/api/PublicController.java | 267 +++++++++++++ .../xncoding/jwt/api/model/BaseResponse.java | 60 +++ .../com/xncoding/jwt/api/model/BindParam.java | 35 ++ .../jwt/api/model/JoinBindResponse.java | 36 ++ .../xncoding/jwt/api/model/LoginParam.java | 59 +++ .../com/xncoding/jwt/api/model/PosParam.java | 119 ++++++ .../xncoding/jwt/api/model/ReportParam.java | 35 ++ .../xncoding/jwt/api/model/UnbindParam.java | 35 ++ .../xncoding/jwt/api/model/VersionParam.java | 47 +++ .../xncoding/jwt/api/model/VersionResult.java | 85 +++++ .../jwt/common/constant/ConstantsList.java | 37 ++ .../xncoding/jwt/common/constant/DictMap.java | 80 ++++ .../xncoding/jwt/common/dao/entity/App.java | 264 +++++++++++++ .../jwt/common/dao/entity/AppPublish.java | 132 +++++++ .../jwt/common/dao/entity/Manager.java | 242 ++++++++++++ .../jwt/common/dao/entity/ManagerRole.java | 132 +++++++ .../jwt/common/dao/entity/OperationLog.java | 198 ++++++++++ .../jwt/common/dao/entity/Permission.java | 132 +++++++ .../xncoding/jwt/common/dao/entity/Pos.java | 352 ++++++++++++++++++ .../jwt/common/dao/entity/PosHistory.java | 176 +++++++++ .../jwt/common/dao/entity/PosMonitor.java | 198 ++++++++++ .../jwt/common/dao/entity/Project.java | 154 ++++++++ .../jwt/common/dao/entity/ProjectUser.java | 132 +++++++ .../xncoding/jwt/common/dao/entity/Role.java | 132 +++++++ .../jwt/common/dao/entity/RolePermission.java | 132 +++++++ .../xncoding/jwt/common/util/CommonUtil.java | 41 ++ .../xncoding/jwt/common/util/DateUtil.java | 296 +++++++++++++++ .../com/xncoding/jwt/common/util/JWTUtil.java | 173 +++++++++ .../com/xncoding/jwt/config/ShiroConfig.java | 134 +++++++ .../xncoding/jwt/dao/entity/ManagerInfo.java | 97 +++++ .../com/xncoding/jwt/dao/entity/SysRole.java | 29 ++ .../jwt/exception/ForbiddenUserException.java | 14 + .../jwt/exception/UnauthorizedException.java | 18 + .../com/xncoding/jwt/service/ApiService.java | 146 ++++++++ .../jwt/service/ManagerInfoService.java | 45 +++ .../com/xncoding/jwt/shiro/JWTFilter.java | 94 +++++ .../java/com/xncoding/jwt/shiro/JWTToken.java | 23 ++ .../com/xncoding/jwt/shiro/MyShiroRealm.java | 121 ++++++ .../java/com/xncoding/jwt/shiro/ShiroKit.java | 187 ++++++++++ .../src/main/resources/application.yml | 46 +++ springboot-jwt/src/main/resources/ehcache.xml | 66 ++++ .../com/xncoding/jwt/ApplicationTests.java | 15 + .../java/com/xncoding/jwt/SimpleTest.java | 37 ++ .../jwt/common/util/CommonUtilTest.java | 24 ++ .../src/test/resources/keystore.jks | Bin 0 -> 1334 bytes 54 files changed, 5302 insertions(+) create mode 100644 springboot-jwt/.gitignore create mode 100644 springboot-jwt/LICENSE create mode 100644 springboot-jwt/README.md create mode 100644 springboot-jwt/pom.xml create mode 100644 springboot-jwt/run.sh create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/Application.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/api/ExceptionController.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/api/LoginController.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/api/NotifyController.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/api/PublicController.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/api/model/BaseResponse.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/api/model/BindParam.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/api/model/JoinBindResponse.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/api/model/LoginParam.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/api/model/PosParam.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/api/model/ReportParam.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/api/model/UnbindParam.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/api/model/VersionParam.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/api/model/VersionResult.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/common/constant/ConstantsList.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/common/constant/DictMap.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/App.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/AppPublish.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/Manager.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/ManagerRole.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/OperationLog.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/Permission.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/Pos.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/PosHistory.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/PosMonitor.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/Project.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/ProjectUser.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/Role.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/RolePermission.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/common/util/CommonUtil.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/common/util/DateUtil.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/common/util/JWTUtil.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/config/ShiroConfig.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/dao/entity/ManagerInfo.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/dao/entity/SysRole.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/exception/ForbiddenUserException.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/exception/UnauthorizedException.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/service/ApiService.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/service/ManagerInfoService.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/shiro/JWTFilter.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/shiro/JWTToken.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/shiro/MyShiroRealm.java create mode 100644 springboot-jwt/src/main/java/com/xncoding/jwt/shiro/ShiroKit.java create mode 100644 springboot-jwt/src/main/resources/application.yml create mode 100644 springboot-jwt/src/main/resources/ehcache.xml create mode 100644 springboot-jwt/src/test/java/com/xncoding/jwt/ApplicationTests.java create mode 100644 springboot-jwt/src/test/java/com/xncoding/jwt/SimpleTest.java create mode 100644 springboot-jwt/src/test/java/com/xncoding/jwt/common/util/CommonUtilTest.java create mode 100644 springboot-jwt/src/test/resources/keystore.jks diff --git a/springboot-jwt/.gitignore b/springboot-jwt/.gitignore new file mode 100644 index 0000000..b71e0c4 --- /dev/null +++ b/springboot-jwt/.gitignore @@ -0,0 +1,17 @@ +# 此为注释– 将被Git 忽略 +# /结尾表示是目录,忽略目录和目录下的所有件 +# /开头表示根目录,否则是.gitignore的相对目录 +# !开头表示反选 +.idea/ +target/ +*.iml +*.ipr +*.iws +*.log +.svn/ +.project +rebel.xml +.rebel-remote.xml.* +swagger.json +swagger.adoc + diff --git a/springboot-jwt/LICENSE b/springboot-jwt/LICENSE new file mode 100644 index 0000000..83cd47d --- /dev/null +++ b/springboot-jwt/LICENSE @@ -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. diff --git a/springboot-jwt/README.md b/springboot-jwt/README.md new file mode 100644 index 0000000..70bf0c2 --- /dev/null +++ b/springboot-jwt/README.md @@ -0,0 +1,20 @@ + +## 简介 + +一般来讲,对于RESTful API都会有认证(Authentication)和授权(Authorization)过程,保证API的安全性。 + +采用TOKEN认证,这种方式也是再HTTP头中,使用Authorization: Bearer ,使用最广泛的TOKEN是JWT,通过签名过的TOKEN。 + +基于Shiro+JWT可实现Token认证方式 + +## 测试 + +启动应用后,先访问登录接口,使用参数用户名=admin/密码=12345678,拿到token后再访问其他接口。 + +## 许可证 + +Copyright (c) 2018 Xiong Neng + +基于 MIT 协议发布: + + diff --git a/springboot-jwt/pom.xml b/springboot-jwt/pom.xml new file mode 100644 index 0000000..cd21dbe --- /dev/null +++ b/springboot-jwt/pom.xml @@ -0,0 +1,136 @@ + + + 4.0.0 + + com.xncoding + springboot-jwt + 1.0.0-SNAPSHOT + jar + + springboot-jwt + 集成JWT实现接口权限认证 + + + org.springframework.boot + spring-boot-starter-parent + 1.5.9.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + org.springframework.boot + spring-boot-starter-jetty + + + com.auth0 + java-jwt + 3.3.0 + + + org.springframework.boot + spring-boot-starter-test + test + + + com.vaadin.external.google + android-json + + + + + + org.apache.shiro + shiro-spring + 1.4.0 + + + slf4j-api + org.slf4j + + + + + + org.apache.shiro + shiro-ehcache + 1.4.0 + + + slf4j-api + org.slf4j + + + + + + org.apache.commons + commons-lang3 + 3.7 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.20 + + + ${project.basedir}/src/main/resources/swagger + ${project.basedir}/src/main/resources/swagger/swagger + + true + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + + src/main/resources + + + src/main/java + + **/*.xml + + + + + + \ No newline at end of file diff --git a/springboot-jwt/run.sh b/springboot-jwt/run.sh new file mode 100644 index 0000000..955efb1 --- /dev/null +++ b/springboot-jwt/run.sh @@ -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 diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/Application.java b/springboot-jwt/src/main/java/com/xncoding/jwt/Application.java new file mode 100644 index 0000000..e180aef --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/Application.java @@ -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); + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/api/ExceptionController.java b/springboot-jwt/src/main/java/com/xncoding/jwt/api/ExceptionController.java new file mode 100644 index 0000000..c9f2292 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/api/ExceptionController.java @@ -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); + } +} + diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/api/LoginController.java b/springboot-jwt/src/main/java/com/xncoding/jwt/api/LoginController.java new file mode 100644 index 0000000..6efa0ed --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/api/LoginController.java @@ -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 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 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); + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/api/NotifyController.java b/springboot-jwt/src/main/java/com/xncoding/jwt/api/NotifyController.java new file mode 100644 index 0000000..229a212 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/api/NotifyController.java @@ -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); + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/api/PublicController.java b/springboot-jwt/src/main/java/com/xncoding/jwt/api/PublicController.java new file mode 100644 index 0000000..4537a74 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/api/PublicController.java @@ -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 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 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); + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/BaseResponse.java b/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/BaseResponse.java new file mode 100644 index 0000000..3e587f7 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/BaseResponse.java @@ -0,0 +1,60 @@ +package com.xncoding.jwt.api.model; + +/** + * API接口的基础返回类 + * + * @author XiongNeng + * @version 1.0 + * @since 2018/1/7 + */ +public class BaseResponse { + /** + * 是否成功 + */ + 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; + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/BindParam.java b/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/BindParam.java new file mode 100644 index 0000000..ac58027 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/BindParam.java @@ -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; + } +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/JoinBindResponse.java b/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/JoinBindResponse.java new file mode 100644 index 0000000..79b3372 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/JoinBindResponse.java @@ -0,0 +1,36 @@ +package com.xncoding.jwt.api.model; + +/** + * 入网绑定返回 + * + * @author XiongNeng + * @version 1.0 + * @since 2018/1/16 + */ +public class JoinBindResponse extends BaseResponse { + /** + * 返回码 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; + } +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/LoginParam.java b/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/LoginParam.java new file mode 100644 index 0000000..b11e836 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/LoginParam.java @@ -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; + } +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/PosParam.java b/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/PosParam.java new file mode 100644 index 0000000..5e63568 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/PosParam.java @@ -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; + } +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/ReportParam.java b/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/ReportParam.java new file mode 100644 index 0000000..e7d2937 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/ReportParam.java @@ -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; + } +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/UnbindParam.java b/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/UnbindParam.java new file mode 100644 index 0000000..500e750 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/UnbindParam.java @@ -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; + } +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/VersionParam.java b/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/VersionParam.java new file mode 100644 index 0000000..1503baf --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/VersionParam.java @@ -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; + } +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/VersionResult.java b/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/VersionResult.java new file mode 100644 index 0000000..d4f8b15 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/api/model/VersionResult.java @@ -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; + } +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/common/constant/ConstantsList.java b/springboot-jwt/src/main/java/com/xncoding/jwt/common/constant/ConstantsList.java new file mode 100644 index 0000000..cbca0e3 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/common/constant/ConstantsList.java @@ -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 INCOME_TYPE_LIST = new ArrayList() {{ + add("租金"); + add("市场管理费"); + add("物业管理费"); + add("其他"); + }}; + + // 市场列表 + public static final List MARKET_LIST = new ArrayList() {{ + add("一期市场"); + add("二期市场"); + add("三期市场"); + }}; + + // 业态 + public static final List BUSINESS_LIST = new ArrayList() {{ + add("男装"); + add("女装"); + add("玩具"); + add("餐饮"); + add("家具"); + }}; +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/common/constant/DictMap.java b/springboot-jwt/src/main/java/com/xncoding/jwt/common/constant/DictMap.java new file mode 100644 index 0000000..bc914ae --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/common/constant/DictMap.java @@ -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> _imap = new HashMap<>(); + + static { + _imap.put(KEY_USER_STATUS, new TreeMap() {{ + put(1, "正常"); + put(2, "禁用"); + }}); + _imap.put(KEY_POS_POS_STATUS, new TreeMap() {{ + put(1, "正常"); + put(2, "故障"); + put(3, "维修中(返厂)"); + put(4, "已禁用(丢失)"); + put(5, "已停用(回收)"); + }}); + _imap.put(KEY_POS_MONITOR_STATUS, new TreeMap() {{ + put(1, "在线"); + put(2, "离线"); + }}); + _imap.put(KEY_APP_PUBLISH_RANGE, new TreeMap() {{ + put(1, "全网发布"); + put(2, "灰度发布"); + }}); + } + + /** + * 根据字典类型key获取某个字典Map + * + * @param type 常量类型 + * @return 字典Map + */ + public static TreeMap 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; + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/App.java b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/App.java new file mode 100644 index 0000000..d849495 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/App.java @@ -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; + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/AppPublish.java b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/AppPublish.java new file mode 100644 index 0000000..bdad4de --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/AppPublish.java @@ -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; + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/Manager.java b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/Manager.java new file mode 100644 index 0000000..980ccf0 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/Manager.java @@ -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; + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/ManagerRole.java b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/ManagerRole.java new file mode 100644 index 0000000..8ea4d4c --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/ManagerRole.java @@ -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; + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/OperationLog.java b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/OperationLog.java new file mode 100644 index 0000000..3c8beea --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/OperationLog.java @@ -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; + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/Permission.java b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/Permission.java new file mode 100644 index 0000000..41c9af7 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/Permission.java @@ -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; + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/Pos.java b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/Pos.java new file mode 100644 index 0000000..f070b31 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/Pos.java @@ -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; + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/PosHistory.java b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/PosHistory.java new file mode 100644 index 0000000..b8257b0 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/PosHistory.java @@ -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; + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/PosMonitor.java b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/PosMonitor.java new file mode 100644 index 0000000..d800e94 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/PosMonitor.java @@ -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; + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/Project.java b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/Project.java new file mode 100644 index 0000000..3603694 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/Project.java @@ -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; + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/ProjectUser.java b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/ProjectUser.java new file mode 100644 index 0000000..abbff86 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/ProjectUser.java @@ -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; + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/Role.java b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/Role.java new file mode 100644 index 0000000..c9d9475 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/Role.java @@ -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; + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/RolePermission.java b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/RolePermission.java new file mode 100644 index 0000000..f246604 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/common/dao/entity/RolePermission.java @@ -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; + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/common/util/CommonUtil.java b/springboot-jwt/src/main/java/com/xncoding/jwt/common/util/CommonUtil.java new file mode 100644 index 0000000..6b28c11 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/common/util/CommonUtil.java @@ -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; + } + } +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/common/util/DateUtil.java b/springboot-jwt/src/main/java/com/xncoding/jwt/common/util/DateUtil.java new file mode 100644 index 0000000..120de61 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/common/util/DateUtil.java @@ -0,0 +1,296 @@ +/** + * Copyright (c) 2015-2016, Chill Zhuang 庄骞 (smallchill@163.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package 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; + } + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/common/util/JWTUtil.java b/springboot-jwt/src/main/java/com/xncoding/jwt/common/util/JWTUtil.java new file mode 100644 index 0000000..d2a5ac5 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/common/util/JWTUtil.java @@ -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; + } + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/config/ShiroConfig.java b/springboot-jwt/src/main/java/com/xncoding/jwt/config/ShiroConfig.java new file mode 100644 index 0000000..19e7130 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/config/ShiroConfig.java @@ -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、部分过滤器可指定参数,如perms,roles + */ + @Bean + public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { + + ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); + // 必须设置 SecurityManager + shiroFilterFactoryBean.setSecurityManager(securityManager); + //验证码过滤器 + Map filtersMap = shiroFilterFactoryBean.getFilters(); + filtersMap.put("jwt", new JWTFilter()); + shiroFilterFactoryBean.setFilters(filtersMap); + + // 拦截器 + //rest:比如/admins/user/**=rest[user],根据请求的方法,相当于/admins/user/**=perms[user:method] ,其中method为post,get,delete等。 + //port:比如/admins/user/**=port[8081],当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString是你访问的url里的?后面的参数。 + //perms:比如/admins/user/**=perms[user:add:*],perms参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,比如/admins/user/**=perms["user:add:*,user:modify:*"],当有多个参数时必须每个参数都通过才通过,想当于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 filterChainDefinitionMap = new LinkedHashMap(); + + // 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; + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/dao/entity/ManagerInfo.java b/springboot-jwt/src/main/java/com/xncoding/jwt/dao/entity/ManagerInfo.java new file mode 100644 index 0000000..74951d9 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/dao/entity/ManagerInfo.java @@ -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 pidsList; + + /** + * 一个管理员具有多个角色 + */ + private List roles;// 一个用户具有多个角色 + + public ManagerInfo() { + } + + public List getRoles() { + return roles; + } + + public void setRoles(List 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 getPidsList() { + return pidsList; + } + + public void setPidsList(List 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()); + } +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/dao/entity/SysRole.java b/springboot-jwt/src/main/java/com/xncoding/jwt/dao/entity/SysRole.java new file mode 100644 index 0000000..a3205a6 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/dao/entity/SysRole.java @@ -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 permissions; + + public SysRole() { + } + + public List getPermissions() { + return permissions; + } + + public void setPermissions(List permissions) { + this.permissions = permissions; + } +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/exception/ForbiddenUserException.java b/springboot-jwt/src/main/java/com/xncoding/jwt/exception/ForbiddenUserException.java new file mode 100644 index 0000000..d537640 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/exception/ForbiddenUserException.java @@ -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 { + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/exception/UnauthorizedException.java b/springboot-jwt/src/main/java/com/xncoding/jwt/exception/UnauthorizedException.java new file mode 100644 index 0000000..30074bf --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/exception/UnauthorizedException.java @@ -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(); + } +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/service/ApiService.java b/springboot-jwt/src/main/java/com/xncoding/jwt/service/ApiService.java new file mode 100644 index 0000000..141ebc0 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/service/ApiService.java @@ -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; + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/service/ManagerInfoService.java b/springboot-jwt/src/main/java/com/xncoding/jwt/service/ManagerInfoService.java new file mode 100644 index 0000000..daa87d6 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/service/ManagerInfoService.java @@ -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 roles = new ArrayList<>(); + SysRole role = new SysRole(); + role.setId(1); + role.setRole("admin"); + role.setDescription("超级管理员"); + roles.add(role); + managerInfo.setRoles(roles); + return managerInfo; + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/shiro/JWTFilter.java b/springboot-jwt/src/main/java/com/xncoding/jwt/shiro/JWTFilter.java new file mode 100644 index 0000000..3c256d2 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/shiro/JWTFilter.java @@ -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,请求会被直接拦截,用户看不到任何东西 + * 所以我们在这里返回true,Controller中可以通过 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()); + } + } +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/shiro/JWTToken.java b/springboot-jwt/src/main/java/com/xncoding/jwt/shiro/JWTToken.java new file mode 100644 index 0000000..c74297c --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/shiro/JWTToken.java @@ -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; + } +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/shiro/MyShiroRealm.java b/springboot-jwt/src/main/java/com/xncoding/jwt/shiro/MyShiroRealm.java new file mode 100644 index 0000000..abc84a6 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/shiro/MyShiroRealm.java @@ -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的时候才会进行回调. + *

+ * 权限信息.(授权): + * 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; + } + +} diff --git a/springboot-jwt/src/main/java/com/xncoding/jwt/shiro/ShiroKit.java b/springboot-jwt/src/main/java/com/xncoding/jwt/shiro/ShiroKit.java new file mode 100644 index 0000000..9a77dc1 --- /dev/null +++ b/springboot-jwt/src/main/java/com/xncoding/jwt/shiro/ShiroKit.java @@ -0,0 +1,187 @@ +/** + * Copyright (c) 2015-2017, Chill Zhuang 庄骞 (smallchill@163.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package 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 ""; + } + +} diff --git a/springboot-jwt/src/main/resources/application.yml b/springboot-jwt/src/main/resources/application.yml new file mode 100644 index 0000000..dc49391 --- /dev/null +++ b/springboot-jwt/src/main/resources/application.yml @@ -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 diff --git a/springboot-jwt/src/main/resources/ehcache.xml b/springboot-jwt/src/main/resources/ehcache.xml new file mode 100644 index 0000000..b580e22 --- /dev/null +++ b/springboot-jwt/src/main/resources/ehcache.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + diff --git a/springboot-jwt/src/test/java/com/xncoding/jwt/ApplicationTests.java b/springboot-jwt/src/test/java/com/xncoding/jwt/ApplicationTests.java new file mode 100644 index 0000000..7a7d2b8 --- /dev/null +++ b/springboot-jwt/src/test/java/com/xncoding/jwt/ApplicationTests.java @@ -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 { + +} diff --git a/springboot-jwt/src/test/java/com/xncoding/jwt/SimpleTest.java b/springboot-jwt/src/test/java/com/xncoding/jwt/SimpleTest.java new file mode 100644 index 0000000..e403c44 --- /dev/null +++ b/springboot-jwt/src/test/java/com/xncoding/jwt/SimpleTest.java @@ -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); + } +} diff --git a/springboot-jwt/src/test/java/com/xncoding/jwt/common/util/CommonUtilTest.java b/springboot-jwt/src/test/java/com/xncoding/jwt/common/util/CommonUtilTest.java new file mode 100644 index 0000000..c656e25 --- /dev/null +++ b/springboot-jwt/src/test/java/com/xncoding/jwt/common/util/CommonUtilTest.java @@ -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()); + } +} \ No newline at end of file diff --git a/springboot-jwt/src/test/resources/keystore.jks b/springboot-jwt/src/test/resources/keystore.jks new file mode 100644 index 0000000000000000000000000000000000000000..a714115b265f23b6e072e95aa91d1ee892bdc2c0 GIT binary patch literal 1334 zcmezO_TO6u1_mY|W&~rllGNgotL8FFTi2PkQ-$*RMNTD@?B(*yu80`TZw(iLXWCCGw{pP?BzV?t1+$ z%aISwOzWL2HCLNV-#6pt{2MbCeN#7?aZaN@*-v0rThp8EF*hVSn_|I zsyk!7e zYLnjVMQyt!b7n0(ZK>1nP-C;~QfZ~c3Ln~o7}?wj5;p*?f|A%)!!r?5_4{8;gL z)Zqo*eeHIOybj1FYfkcF=3%FX^9b2r(y*(Ge6#$!E& z^pyuXS69jBmcBCHwNEEy_0IG&GQAsWnRMr}-~0A|r_+YrwYx6PPUI5VE3tKn4A<8S z(^8LUnRPC43w~l|X;_?ni+^EpuNh0hjaNHQ{Ql85eb(IgWyvy|mX;mNPWU(@mRVZ) zs*}apq!L&4)Vv4lMYEk~u>_OEK}wHrYKpI5}JEVo=Z7w<;MkHQKL=FF%>S?SDJt=KuGdDutd+ z(Ed8-2+y?t@s)GGEV;^S_t=r=ao5RbPpVpV#qZj__SR53E<10Tnl-vN&S2tXm~2_bFEyv@g#j-cr&gOs+jm}Ix@KiCh%w|g;ACSCWnmL$att*T zHV_1HIC!{%^K(;mgG&-iQVkUiC6x+3B`JoY z2ErgE%sf2h<>h*yOr@8cpKBl|&TD97U}0=%Xl`U|Y#asVS{fTbxiq%DaXzwdf!Ub3 zv6sQ1v6HE>k>OIZNq+5w9d9|NE#K)Vz5LjMh?ljwY^<)Y9`yFs9h%hnwnA>h5)Jv) zCN2i&eIJKMy*oESn=>q-!7}UG4AtLCUp5P#E_jowQ1op2;#2NC6PMT7?2BJhCz7qq z@N`L~aLKL(K{GV}n%-FQW#@P2%VoJoEAv0dirYAuO*hK7lZj2-txt-0wanWV-{$=~;pSb^?#h&B0kAUe7shx_i zGoOeh#H@R$vcJhmpV7Cln)j5QQhD<1#f>v(t_f-T!}CsPe$!c=yrMV$)-TlAFETX# z-4yvhdtt>*Q)zjnr~cV4v#wi7E|l$7&UjqgZP_cc|Dp-A!NNBW7FgC8J-#kk@@x0% Gy#D|dcP%;q literal 0 HcmV?d00001