diff --git a/config/application-local.properties b/config/application-local.properties index a41bc089..67df684c 100644 --- a/config/application-local.properties +++ b/config/application-local.properties @@ -2,7 +2,7 @@ server.port=9276 # 根据自身环境修改 server.tomcat.basedir=./basedir # 多个项目放在nginx下同个端口,通过该配置区分 -server.servlet.context-path=/phoenix +server.servlet.context-path=/dispose # 配置数据源 spring.datasource.url=jdbc:mysql://172.28.72.118:33061/dispose?serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull&useUnicode=true diff --git a/src/main/java/com/cmcc/hy/phoenix/common/ConstValue.java b/src/main/java/com/cmcc/hy/phoenix/common/ConstValue.java index b99f437b..6074ada5 100644 --- a/src/main/java/com/cmcc/hy/phoenix/common/ConstValue.java +++ b/src/main/java/com/cmcc/hy/phoenix/common/ConstValue.java @@ -1,6 +1,11 @@ package com.cmcc.hy.phoenix.common; public class ConstValue { + public class GlobalConfigure { + public static final int TOKEN_TIMEOUT_MS = 30 * 60 * 1000; + public static final int ALLOW_PWD_ERR_TIMES = 5; + } + public class SOAPWrapperConst { public static final String NAMESPACE_URI = "http://10.88.77.15/UMC/service/AbnormalFlowCleaningService"; public static final String SERVICE_ADDRESS = "http://10.88.77.15/UMC/service/AbnormalFlowCleaningService?wsdl"; @@ -16,10 +21,20 @@ public class ConstValue { public static final int CRYPTO_AES256 = 2; } + public class ProtocolCmdId { + public static final int AUTH_LOGIN = 10; + public static final int AUTH_LOGOUT = 11; + } + public enum DisposeDevice { DPTECH_UMC, HAOHAN_PLATFORM; } + public class UserAccountStatus { + public static final int NORMAL = 0; + public static final int LOCKED = 1; + } + /** * @brief 错误码常量定义 */ @@ -27,7 +42,7 @@ public class ConstValue { ERR_OK (0, "成功"), ERR_PASSWORD (1, "密码错误"), ERR_USERNOTFOUND (2, "用户不存在"), - ERR_PASSWORDMORE (3, "连续密码错误达3次,再次输入错误将锁定用户"), + ERR_PASSWORDMORE (3, "连续密码错误达上限,再次输入错误将锁定用户"), ERR_USERLOCK (4, "密码错误达上限,用户被锁定"), ERR_ACCOUNT (5, "用户账户异常"), ERR_USEREXIST (6, "该用户已经存在"), @@ -37,6 +52,11 @@ public class ConstValue { ERR_PERMISSION (10, "操作员权限不足"), ERR_REQTIMEOUT (11, "请求超时"), ERR_PARAMS (12, "参数错误"), + ERR_EXCEPTION (13, "系统异常"), + ERR_UNKNOWNCMD (14, "未知命令"), + ERR_LOGOUT (15, "用户未登录"), + ERR_TOKENTIMEOUT (16, "Token超时"), + ERR_TOKENNOTFOUND (17, "非法Token"), ; private int errno; @@ -51,6 +71,14 @@ public class ConstValue { return errno; } + public int getHttpCode() { + if(this.errno == 0) { + return 200; + } else { + return 500 + this.errno; + } + } + public String getMsg() { return errMsg; } diff --git a/src/main/java/com/cmcc/hy/phoenix/config/SetupInit.java b/src/main/java/com/cmcc/hy/phoenix/config/SetupInit.java new file mode 100644 index 00000000..1ec0f7bc --- /dev/null +++ b/src/main/java/com/cmcc/hy/phoenix/config/SetupInit.java @@ -0,0 +1,23 @@ +package com.cmcc.hy.phoenix.config; + +import com.cmcc.hy.phoenix.pojo.po.UserAccountCache; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +@Component +@Slf4j +public class SetupInit implements CommandLineRunner { + + //@Resource + //private UserAccountCache userAccount; + + @Override + public void run(String... args) throws Exception { + // TODO Auto-generated method stub + log.info("System Setup................................................"); + //fileLoadService.mailFileRefresh(); + } +} diff --git a/src/main/java/com/cmcc/hy/phoenix/controller/AuthController.java b/src/main/java/com/cmcc/hy/phoenix/controller/AuthController.java new file mode 100644 index 00000000..acea3ba6 --- /dev/null +++ b/src/main/java/com/cmcc/hy/phoenix/controller/AuthController.java @@ -0,0 +1,148 @@ +package com.cmcc.hy.phoenix.controller; + +import cn.hutool.core.convert.Convert; +import com.cmcc.hy.phoenix.annotation.bodyencdec.ReqDec; +import com.cmcc.hy.phoenix.common.ConstValue; +import com.cmcc.hy.phoenix.mapper.UserAccountMapper; +import com.cmcc.hy.phoenix.pojo.dto.ProtocolDTO; +import com.cmcc.hy.phoenix.pojo.entity.UserAccount; +import com.cmcc.hy.phoenix.pojo.vo.*; +import com.cmcc.hy.phoenix.service.LoginService; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.Builder; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.binary.Hex; +import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.MissingRequestHeaderException; +import org.springframework.web.bind.annotation.*; +import tk.mybatis.mapper.entity.Example; + +import javax.annotation.Resource; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.*; + +import static com.sun.corba.se.impl.util.RepositoryId.cache; + +@Controller +@RequestMapping(value = "/handle") +@Slf4j +@Api(value = "抗DDoS处置平台认证接口", tags = "抗DDoS处置平台认证接口") +@Component +public class AuthController { + @Resource + private ObjectMapper objectMapper; + + @Resource + private LoginService loginService; + + @PostMapping("/login") + @ResponseBody + @ApiOperation("获取版本信息") + @ReqDec + @Builder + public ProtocolResp UserLogin(@RequestBody(required = true) ProtocolDTO mr, + @RequestHeader HttpHeaders headers) { + String msgCtx = ""; + ConstValue.ErrorCode err = ConstValue.ErrorCode.ERR_OK; + + log.info("请求token: {}", headers.get("Authorization")); + log.info("请求参数 {}", mr); + + if(mr == null) { + err = ConstValue.ErrorCode.ERR_PARAMS; + return ProtocolResp.result(err, -1, msgCtx); + } else if (mr.IsRequestTimeout()) { + err = ConstValue.ErrorCode.ERR_REQTIMEOUT; + } else { + try { + if(mr.getCmdId() == ConstValue.ProtocolCmdId.AUTH_LOGIN) { + EnumMap loginMap = userLogin(mr); + err = loginMap.keySet().iterator().next(); + msgCtx = loginMap.get(err); + } else if (mr.getCmdId() == ConstValue.ProtocolCmdId.AUTH_LOGOUT) { + + if(headers.get("Authorization") == null + || Objects.requireNonNull(headers.get("Authorization")).size() == 0) { + err = ConstValue.ErrorCode.ERR_LOGOUT; + } else { + EnumMap loginMap = userLogout(mr, + Objects.requireNonNull(headers.get("Authorization")).get(0)); + err = loginMap.keySet().iterator().next(); + msgCtx = loginMap.get(err); + } + }else { + err = ConstValue.ErrorCode.ERR_UNKNOWNCMD; + } + } catch (JsonProcessingException | NoSuchAlgorithmException ex) { + log.error(ex.getMessage()); + err = ConstValue.ErrorCode.ERR_EXCEPTION; + } + } + + return ProtocolResp.result(err, mr.getCmdId(), msgCtx); + } + + private EnumMap userLogout(ProtocolDTO mr, String token) + throws JsonProcessingException { + EnumMap retMap = new EnumMap<>(ConstValue.ErrorCode.class); + ConstValue.ErrorCode err = ConstValue.ErrorCode.ERR_OK; + + UserLogoutRsp rspInfo = UserLogoutRsp.builder() + .userName("") + .status(err.getCode()) + .message(err.getMsg()).build(); + + UserLogoutReq reqInfo = objectMapper.readValue(mr.getMsgContent(), UserLogoutReq.class); + rspInfo.setUserName(reqInfo.getUserName()); + + err = loginService.logoutService(reqInfo.userName, token.replaceFirst("Bearer ", "")); + + rspInfo.setStatus(err.getCode()); + rspInfo.setMessage(err.getMsg()); + + retMap.put(err, objectMapper.writeValueAsString(rspInfo)); + + return retMap; + } + + private EnumMap userLogin(ProtocolDTO mr) + throws NoSuchAlgorithmException, JsonProcessingException { + EnumMap retMap = new EnumMap<>(ConstValue.ErrorCode.class); + ConstValue.ErrorCode err = ConstValue.ErrorCode.ERR_OK; + + UserLoginRsp rspInfo = UserLoginRsp.builder() + .userName("") + .token("") + .status(err.getCode()) + .message(err.getMsg()) + .expireTime(0L) + .logTime(System.currentTimeMillis()).build(); + + UserLoginReq reqInfo = objectMapper.readValue(mr.getMsgContent(), UserLoginReq.class); + + rspInfo.setUserName(reqInfo.getUserName()); + + EnumMap logMap = loginService.loginService(reqInfo.getUserName(), + reqInfo.getPassword()); + + if(logMap.isEmpty()) { + err = ConstValue.ErrorCode.ERR_USERNOTFOUND; + } else { + err = logMap.keySet().iterator().next(); + rspInfo.setToken(logMap.get(err)); + } + + rspInfo.setStatus(err.getCode()); + rspInfo.setMessage(err.getMsg()); + + retMap.put(err, objectMapper.writeValueAsString(rspInfo)); + + return retMap; + } +} diff --git a/src/main/java/com/cmcc/hy/phoenix/controller/DebugController.java b/src/main/java/com/cmcc/hy/phoenix/controller/DebugController.java new file mode 100644 index 00000000..3c61be8a --- /dev/null +++ b/src/main/java/com/cmcc/hy/phoenix/controller/DebugController.java @@ -0,0 +1,40 @@ +package com.cmcc.hy.phoenix.controller; + +import com.cmcc.hy.phoenix.annotation.bodyencdec.ReqDec; +import com.cmcc.hy.phoenix.common.ConstValue; +import com.cmcc.hy.phoenix.pojo.dto.ProtocolDTO; +import com.cmcc.hy.phoenix.pojo.vo.ProtocolResp; +import com.cmcc.hy.phoenix.service.UserAccountCacheService; +import com.fasterxml.jackson.core.JsonProcessingException; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.Builder; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; + +@Controller +@RequestMapping(value = "/debug") +@Slf4j +@Api(value = "抗DDoS处置平台调试接口", tags = "抗DDoS处置平台调试接口") +@Component +public class DebugController { + + @Resource + private UserAccountCacheService userAccountService; + + @GetMapping("/cacheuser") + @ResponseBody + @ApiOperation("获取缓存用户") + @ReqDec + @Builder + public ProtocolResp UserLogin(@RequestBody(required = true) ProtocolDTO mr) throws JsonProcessingException { + + return ProtocolResp.result(ConstValue.ErrorCode.ERR_OK, -1, userAccountService.getCacheUser()); + + } +} diff --git a/src/main/java/com/cmcc/hy/phoenix/controller/ProtocolController.java b/src/main/java/com/cmcc/hy/phoenix/controller/ProtocolController.java index 869896b8..a8f78781 100644 --- a/src/main/java/com/cmcc/hy/phoenix/controller/ProtocolController.java +++ b/src/main/java/com/cmcc/hy/phoenix/controller/ProtocolController.java @@ -6,8 +6,8 @@ import com.cmcc.hy.phoenix.common.ConstValue; import com.cmcc.hy.phoenix.help.GitInformation; import com.cmcc.hy.phoenix.pojo.dto.ProtocolDTO; import com.cmcc.hy.phoenix.pojo.vo.Resp; -import com.cmcc.hy.phoenix.vo.GetVersion; -import com.cmcc.hy.phoenix.vo.ProtocolResp; +import com.cmcc.hy.phoenix.pojo.vo.GetVersion; +import com.cmcc.hy.phoenix.pojo.vo.ProtocolResp; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Builder; @@ -53,6 +53,8 @@ public class ProtocolController { if(mr == null) { return ProtocolResp.result(ConstValue.ErrorCode.ERR_PARAMS); + } else if (mr.IsRequestTimeout()) { + return ProtocolResp.result(ConstValue.ErrorCode.ERR_REQTIMEOUT); } try { diff --git a/src/main/java/com/cmcc/hy/phoenix/controller/TestController.java b/src/main/java/com/cmcc/hy/phoenix/controller/TestController.java index c2c94314..50e4ada3 100644 --- a/src/main/java/com/cmcc/hy/phoenix/controller/TestController.java +++ b/src/main/java/com/cmcc/hy/phoenix/controller/TestController.java @@ -24,7 +24,7 @@ import lombok.extern.slf4j.Slf4j; /** * 对外服务定义 - * + * * @author phoenix * @date 2020年2月4日 */ @@ -41,7 +41,7 @@ public class TestController { private UserService userService; /** - * + * * @return */ @PostMapping("/post") @@ -57,7 +57,7 @@ public class TestController { } /** - * + * * @return */ @GetMapping("/ok/{id}") @@ -69,19 +69,19 @@ public class TestController { } /** - * + * * @return */ @GetMapping("/mail") @ResponseBody public MyResp sendMail() { - asyncService.sendMail("这是邮件内容"); + //asyncService.sendMail("这是邮件内容"); log.info("记住我的线程名 {},和实际发送的线程名不一样", Thread.currentThread().getName()); return MyResp.result(Resp.SUCCESS); } /** - * + * * @return */ @GetMapping("/exception") diff --git a/src/main/java/com/cmcc/hy/phoenix/mapper/UserAccountMapper.java b/src/main/java/com/cmcc/hy/phoenix/mapper/UserAccountMapper.java index cd741184..34519bad 100644 --- a/src/main/java/com/cmcc/hy/phoenix/mapper/UserAccountMapper.java +++ b/src/main/java/com/cmcc/hy/phoenix/mapper/UserAccountMapper.java @@ -1,14 +1,20 @@ package com.cmcc.hy.phoenix.mapper; import com.cmcc.hy.phoenix.pojo.entity.UserAccount; +import org.apache.ibatis.annotations.Param; import tk.mybatis.mapper.common.IdsMapper; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.common.MySqlMapper; +import java.sql.Timestamp; import java.util.List; public interface UserAccountMapper extends Mapper, IdsMapper, MySqlMapper { - List getUserByName(String name); + UserAccount getUserByName(String username); + + void lockUserAccount(@Param("username")String username); + void unlockUserAccount(@Param("username")String username); + void refreshLoginTime(@Param("username")String username); } diff --git a/src/main/java/com/cmcc/hy/phoenix/pojo/dto/ProtocolDTO.java b/src/main/java/com/cmcc/hy/phoenix/pojo/dto/ProtocolDTO.java index 0fb84ecf..9f826c80 100644 --- a/src/main/java/com/cmcc/hy/phoenix/pojo/dto/ProtocolDTO.java +++ b/src/main/java/com/cmcc/hy/phoenix/pojo/dto/ProtocolDTO.java @@ -47,13 +47,14 @@ public class ProtocolDTO { private int code; public Boolean IsRequestTimeout() { - Long timeDiff = System.currentTimeMillis() - this.timeStamp; + Long current = System.currentTimeMillis(); + Long timeDiff = current - this.timeStamp; if (timeDiff > 0 && timeDiff <= 3000) { - return true; + return false; } - return true; + return false; } } diff --git a/src/main/java/com/cmcc/hy/phoenix/pojo/entity/UserAccount.java b/src/main/java/com/cmcc/hy/phoenix/pojo/entity/UserAccount.java index ed0baaea..0ac854b9 100644 --- a/src/main/java/com/cmcc/hy/phoenix/pojo/entity/UserAccount.java +++ b/src/main/java/com/cmcc/hy/phoenix/pojo/entity/UserAccount.java @@ -50,10 +50,6 @@ public class UserAccount implements Serializable { */ private String lastLoginTime; - /** - * 连续密码错误次数 - */ - private Integer pwdErrTimes; /** * 账户锁定时间 diff --git a/src/main/java/com/cmcc/hy/phoenix/pojo/po/UserAccountCache.java b/src/main/java/com/cmcc/hy/phoenix/pojo/po/UserAccountCache.java new file mode 100644 index 00000000..6cc05ca6 --- /dev/null +++ b/src/main/java/com/cmcc/hy/phoenix/pojo/po/UserAccountCache.java @@ -0,0 +1,15 @@ +package com.cmcc.hy.phoenix.pojo.po; + +import lombok.*; + +@Setter +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserAccountCache { + private String username; + private String token; + private Long lastAccess; + private Integer pwdErrTimes; +} diff --git a/src/main/java/com/cmcc/hy/phoenix/vo/GetVersion.java b/src/main/java/com/cmcc/hy/phoenix/pojo/vo/GetVersion.java similarity index 66% rename from src/main/java/com/cmcc/hy/phoenix/vo/GetVersion.java rename to src/main/java/com/cmcc/hy/phoenix/pojo/vo/GetVersion.java index 626ec744..cc99ac60 100644 --- a/src/main/java/com/cmcc/hy/phoenix/vo/GetVersion.java +++ b/src/main/java/com/cmcc/hy/phoenix/pojo/vo/GetVersion.java @@ -1,4 +1,4 @@ -package com.cmcc.hy.phoenix.vo; +package com.cmcc.hy.phoenix.pojo.vo; import lombok.Getter; import lombok.Setter; @@ -15,8 +15,4 @@ public class GetVersion { private String commit_time; private String tag_name; private String tags; - - public static GetVersion result(String commit){ - return GetVersion.builder().commit_id(commit).build(); - } } diff --git a/src/main/java/com/cmcc/hy/phoenix/vo/ProtocolResp.java b/src/main/java/com/cmcc/hy/phoenix/pojo/vo/ProtocolResp.java similarity index 83% rename from src/main/java/com/cmcc/hy/phoenix/vo/ProtocolResp.java rename to src/main/java/com/cmcc/hy/phoenix/pojo/vo/ProtocolResp.java index 3ba04f6d..ccd149ce 100644 --- a/src/main/java/com/cmcc/hy/phoenix/vo/ProtocolResp.java +++ b/src/main/java/com/cmcc/hy/phoenix/pojo/vo/ProtocolResp.java @@ -1,7 +1,6 @@ -package com.cmcc.hy.phoenix.vo; +package com.cmcc.hy.phoenix.pojo.vo; import com.cmcc.hy.phoenix.common.ConstValue; -import com.cmcc.hy.phoenix.pojo.vo.Resp; import io.swagger.annotations.ApiModelProperty; import lombok.Builder; import lombok.Getter; @@ -53,41 +52,26 @@ public class ProtocolResp { } public static ProtocolResp result(ConstValue.ErrorCode err) { - int code = Resp.SUCCESS.getCode(); - - if(err.getCode() != 0) { - code = 1000 + err.getCode(); - } - return ProtocolResp.builder() .ver(ConstValue.Protocol.VERSION) .cryptoType(ConstValue.Protocol.CRYPTO_NONE) - .code(code) + .code(err.getHttpCode()) + .timeStamp(System.currentTimeMillis()) .msgContent(err.getMsg()).build(); } public static ProtocolResp result(ConstValue.ErrorCode err, Integer cmdId, String respMsg) { - int code = Resp.SUCCESS.getCode(); - - if(err.getCode() != 0) { - code = 1000 + err.getCode(); - } - return result(err, cmdId, respMsg, ConstValue.Protocol.CRYPTO_NONE); } public static ProtocolResp result(ConstValue.ErrorCode err, Integer cmdId, String respMsg, Integer crypto) { - int code = Resp.SUCCESS.getCode(); - - if(err.getCode() != 0) { - code = 1000 + err.getCode(); - } return ProtocolResp.builder() .cmdId(cmdId + ConstValue.Protocol.RESP_CMD_BASE) .ver(ConstValue.Protocol.VERSION) .cryptoType(crypto) - .code(code) + .timeStamp(System.currentTimeMillis()) + .code(err.getHttpCode()) .msgContent(respMsg).build(); } } diff --git a/src/main/java/com/cmcc/hy/phoenix/pojo/vo/UserLoginReq.java b/src/main/java/com/cmcc/hy/phoenix/pojo/vo/UserLoginReq.java new file mode 100644 index 00000000..2d9b8bff --- /dev/null +++ b/src/main/java/com/cmcc/hy/phoenix/pojo/vo/UserLoginReq.java @@ -0,0 +1,11 @@ +package com.cmcc.hy.phoenix.pojo.vo; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class UserLoginReq { + public String userName; + public String password; +} diff --git a/src/main/java/com/cmcc/hy/phoenix/pojo/vo/UserLoginRsp.java b/src/main/java/com/cmcc/hy/phoenix/pojo/vo/UserLoginRsp.java new file mode 100644 index 00000000..9b44365f --- /dev/null +++ b/src/main/java/com/cmcc/hy/phoenix/pojo/vo/UserLoginRsp.java @@ -0,0 +1,19 @@ +package com.cmcc.hy.phoenix.pojo.vo; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +@Builder +public class UserLoginRsp { + private String userName; + private String token; + private Long logTime; + private Long expireTime; + private Integer status; + private String message; +} diff --git a/src/main/java/com/cmcc/hy/phoenix/pojo/vo/UserLogoutReq.java b/src/main/java/com/cmcc/hy/phoenix/pojo/vo/UserLogoutReq.java new file mode 100644 index 00000000..849c9426 --- /dev/null +++ b/src/main/java/com/cmcc/hy/phoenix/pojo/vo/UserLogoutReq.java @@ -0,0 +1,11 @@ +package com.cmcc.hy.phoenix.pojo.vo; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class UserLogoutReq { + public String userName; + public String token; +} \ No newline at end of file diff --git a/src/main/java/com/cmcc/hy/phoenix/pojo/vo/UserLogoutRsp.java b/src/main/java/com/cmcc/hy/phoenix/pojo/vo/UserLogoutRsp.java new file mode 100644 index 00000000..ea823742 --- /dev/null +++ b/src/main/java/com/cmcc/hy/phoenix/pojo/vo/UserLogoutRsp.java @@ -0,0 +1,16 @@ +package com.cmcc.hy.phoenix.pojo.vo; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +@Builder +public class UserLogoutRsp { + private String userName; + private Integer status; + private String message; +} diff --git a/src/main/java/com/cmcc/hy/phoenix/service/AsyncService.java b/src/main/java/com/cmcc/hy/phoenix/service/AsyncService.java index 0b4f2208..e193d718 100644 --- a/src/main/java/com/cmcc/hy/phoenix/service/AsyncService.java +++ b/src/main/java/com/cmcc/hy/phoenix/service/AsyncService.java @@ -1,18 +1,13 @@ package com.cmcc.hy.phoenix.service; /** - * - * + * + * * @author phoenix * @date 2020年2月7日 */ public interface AsyncService { - /** - * - * @Description: 发邮件测试 - * @param cont - */ - public void sendMail(String cont); + } diff --git a/src/main/java/com/cmcc/hy/phoenix/service/LoginService.java b/src/main/java/com/cmcc/hy/phoenix/service/LoginService.java new file mode 100644 index 00000000..fd995190 --- /dev/null +++ b/src/main/java/com/cmcc/hy/phoenix/service/LoginService.java @@ -0,0 +1,11 @@ +package com.cmcc.hy.phoenix.service; + +import com.cmcc.hy.phoenix.common.ConstValue; + +import java.security.NoSuchAlgorithmException; +import java.util.EnumMap; + +public interface LoginService { + public EnumMap loginService(String username, String password) throws NoSuchAlgorithmException; + public ConstValue.ErrorCode logoutService(String username, String token); +} diff --git a/src/main/java/com/cmcc/hy/phoenix/service/UserAccountCacheService.java b/src/main/java/com/cmcc/hy/phoenix/service/UserAccountCacheService.java new file mode 100644 index 00000000..162140b8 --- /dev/null +++ b/src/main/java/com/cmcc/hy/phoenix/service/UserAccountCacheService.java @@ -0,0 +1,16 @@ +package com.cmcc.hy.phoenix.service; + +import com.cmcc.hy.phoenix.common.ConstValue; +import com.fasterxml.jackson.core.JsonProcessingException; + +import java.security.NoSuchAlgorithmException; + +public interface UserAccountCacheService { + String getUserToken(String username) throws NoSuchAlgorithmException; + int getUsrPwdErrTimes(String username); + void setUserPwdErrTimes(String username, Integer errTimes); + void cleanUserToken(String username); + ConstValue.ErrorCode verifyUserLogin(String username, String token); + + String getCacheUser() throws JsonProcessingException; +} diff --git a/src/main/java/com/cmcc/hy/phoenix/service/impl/AsyncServiceImpl.java b/src/main/java/com/cmcc/hy/phoenix/service/impl/AsyncServiceImpl.java index 82817f28..fbc69c12 100644 --- a/src/main/java/com/cmcc/hy/phoenix/service/impl/AsyncServiceImpl.java +++ b/src/main/java/com/cmcc/hy/phoenix/service/impl/AsyncServiceImpl.java @@ -8,8 +8,8 @@ import com.cmcc.hy.phoenix.service.AsyncService; import lombok.extern.slf4j.Slf4j; /** - * - * + * + * * @author phoenix * @date 2020年2月5日 */ @@ -17,21 +17,6 @@ import lombok.extern.slf4j.Slf4j; @Slf4j public class AsyncServiceImpl implements AsyncService { - /** - * Async(xx) 表明用哪个线程池来完成异步任务,对应ThreadPoolConfig中的线程池定义 - * - * @see com.cmcc.hy.phoenix.service.AsyncService#sendMail(java.lang.String) - */ - @Async("bizExecutor") - @Override - public void sendMail(String cont) { - // TODO Auto-generated method stub - try { - Thread.sleep(5000); - log.info("异步发送邮件,邮件内容 " + cont); - } catch (Throwable e) { - log.error("发送邮件异常", e); - } - } + } diff --git a/src/main/java/com/cmcc/hy/phoenix/service/impl/LoginServiceImpl.java b/src/main/java/com/cmcc/hy/phoenix/service/impl/LoginServiceImpl.java new file mode 100644 index 00000000..b845b8bf --- /dev/null +++ b/src/main/java/com/cmcc/hy/phoenix/service/impl/LoginServiceImpl.java @@ -0,0 +1,87 @@ +package com.cmcc.hy.phoenix.service.impl; + +import com.cmcc.hy.phoenix.common.ConstValue; +import com.cmcc.hy.phoenix.mapper.UserAccountMapper; +import com.cmcc.hy.phoenix.pojo.entity.UserAccount; +import com.cmcc.hy.phoenix.service.LoginService; +import com.cmcc.hy.phoenix.service.UserAccountCacheService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.security.NoSuchAlgorithmException; +import java.util.EnumMap; +import java.util.List; + +@Service +@Slf4j +public class LoginServiceImpl implements LoginService { + @Resource + private UserAccountCacheService userAccountService; + + @Resource + private UserAccountMapper userAccountMapper; + + + @Override + public EnumMap loginService(String username, String password) throws NoSuchAlgorithmException { + EnumMap retMap = new EnumMap<>(ConstValue.ErrorCode.class); + +// Example exp = new Example(UserAccount.class); +// exp.createCriteria().andEqualTo("username", username); + userAccountMapper.refreshLoginTime(username); + UserAccount loginUser = userAccountMapper.getUserByName(username); + + // 用户为空 + if(loginUser == null) { + retMap.put(ConstValue.ErrorCode.ERR_USERNOTFOUND, ""); + } else { + if(loginUser.getStatus() == ConstValue.UserAccountStatus.LOCKED) { + retMap.put(ConstValue.ErrorCode.ERR_USERLOCK, ""); + } else if(!loginUser.getPassword().equals(password)) { + // 密码错误 + int errTimes = userAccountService.getUsrPwdErrTimes(username) + 1; + + // 更新密码错误次数 + userAccountService.setUserPwdErrTimes(username, errTimes); + + if(errTimes == ConstValue.GlobalConfigure.ALLOW_PWD_ERR_TIMES - 1) { + // 提示用户即将锁定账户 + retMap.put(ConstValue.ErrorCode.ERR_PASSWORDMORE, ""); + } else if(errTimes >= ConstValue.GlobalConfigure.ALLOW_PWD_ERR_TIMES) { + // 锁定账户 + retMap.put(ConstValue.ErrorCode.ERR_USERLOCK, ""); + userAccountMapper.lockUserAccount(username); + } else { + retMap.put(ConstValue.ErrorCode.ERR_PASSWORD, ""); + } + } else { + retMap.put(ConstValue.ErrorCode.ERR_OK, userAccountService.getUserToken(username)); + userAccountService.setUserPwdErrTimes(username, 0); + } + } + + return retMap; + } + + @Override + public ConstValue.ErrorCode logoutService(String username, String token) { + ConstValue.ErrorCode err = ConstValue.ErrorCode.ERR_OK; + + UserAccount loginUser = userAccountMapper.getUserByName(username); + + // 用户为空 + if(loginUser == null) { + err = ConstValue.ErrorCode.ERR_USERNOTFOUND; + } else { + + err = userAccountService.verifyUserLogin(username, token); + + if(err == ConstValue.ErrorCode.ERR_OK) { + userAccountService.cleanUserToken(username); + } + } + + return err; + } +} diff --git a/src/main/java/com/cmcc/hy/phoenix/service/impl/UserAccountCacheServiceImpl.java b/src/main/java/com/cmcc/hy/phoenix/service/impl/UserAccountCacheServiceImpl.java new file mode 100644 index 00000000..b76c55d2 --- /dev/null +++ b/src/main/java/com/cmcc/hy/phoenix/service/impl/UserAccountCacheServiceImpl.java @@ -0,0 +1,137 @@ +package com.cmcc.hy.phoenix.service.impl; + +import cn.hutool.core.convert.Convert; +import com.cmcc.hy.phoenix.common.ConstValue; +import com.cmcc.hy.phoenix.pojo.po.UserAccountCache; +import com.cmcc.hy.phoenix.service.UserAccountCacheService; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.binary.Hex; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Random; +import java.util.concurrent.ConcurrentHashMap; + +@Service +@Slf4j +public class UserAccountCacheServiceImpl implements UserAccountCacheService { + + @Resource + private ObjectMapper objectMapper; + + private ConcurrentHashMap userAccountMap = new ConcurrentHashMap<>(); + + @Override + public ConstValue.ErrorCode verifyUserLogin(String username, String token) { + if(!userAccountMap.containsKey(username)) { + return ConstValue.ErrorCode.ERR_USERNOTFOUND; + } + + UserAccountCache uc = userAccountMap.get(username); + if(uc.getToken().length() == 0) { + return ConstValue.ErrorCode.ERR_LOGOUT; + } + + if((System.currentTimeMillis() - uc.getLastAccess()) + >= ConstValue.GlobalConfigure.TOKEN_TIMEOUT_MS) + { + return ConstValue.ErrorCode.ERR_TOKENTIMEOUT; + } + + if(!uc.getToken().equals(token)) { + return ConstValue.ErrorCode.ERR_TOKENNOTFOUND; + } + + return ConstValue.ErrorCode.ERR_OK; + } + + @Override + public String getCacheUser() throws JsonProcessingException { + return objectMapper.writeValueAsString(userAccountMap); + } + + @Override + public void cleanUserToken(String username) { + if(userAccountMap.containsKey(username)) { + UserAccountCache uc = userAccountMap.get(username); + uc.setToken(""); + } + } + + @Override + public int getUsrPwdErrTimes(String username) { + if(userAccountMap.containsKey(username)) { + UserAccountCache uc = userAccountMap.get(username); + return uc.getPwdErrTimes(); + } else { + UserAccountCache uc = UserAccountCache.builder() + .username(username) + .token("") + .lastAccess(System.currentTimeMillis()) + .pwdErrTimes(0) + .lastAccess(System.currentTimeMillis()).build(); + + userAccountMap.put(username, uc); + return 0; + } + } + + @Override + public void setUserPwdErrTimes(String username, Integer errTimes) { + if(userAccountMap.containsKey(username)) { + UserAccountCache uc = userAccountMap.get(username); + + uc.setPwdErrTimes(Math.abs(errTimes)); + } + } + + @Override + public String getUserToken(String username) throws NoSuchAlgorithmException { + if(userAccountMap.containsKey(username)) { + UserAccountCache uc = userAccountMap.get(username); + + if((System.currentTimeMillis() - uc.getLastAccess()) + >= ConstValue.GlobalConfigure.TOKEN_TIMEOUT_MS + || uc.getToken().length() == 0) { + uc.setToken(createUserToken(username)); + log.info("Refresh {} Token:{}", username, uc.getToken()); + } else { + log.info("Get {} Token:{}", username, uc.getToken()); + } + + uc.setLastAccess(System.currentTimeMillis()); + + return uc.getToken(); + } else { + UserAccountCache uc = UserAccountCache.builder() + .username(username) + .token(createUserToken(username)) + .lastAccess(System.currentTimeMillis()) + .pwdErrTimes(0) + .lastAccess(System.currentTimeMillis()).build(); + + userAccountMap.put(username, uc); + + log.info("Create {} Token:{}", username, uc.getToken()); + + return uc.getToken(); + } + } + + private String createUserToken(String username) throws NoSuchAlgorithmException { + // 获取指定摘要算法的messageDigest对象 + MessageDigest messageDigest = MessageDigest.getInstance("SHA-256"); // 此处的sha代表sha1 + + String tokenKey = username + + Convert.toStr(new Random(System.currentTimeMillis()).nextInt()) + + Convert.toStr(System.currentTimeMillis()); + // 调用digest方法,进行加密操作 + byte[] cipherBytes = messageDigest.digest(tokenKey.getBytes()); + + return Hex.encodeHexString(cipherBytes); + } +} diff --git a/src/main/resources/mappers/UserAccount.xml b/src/main/resources/mappers/UserAccount.xml new file mode 100644 index 00000000..519379d3 --- /dev/null +++ b/src/main/resources/mappers/UserAccount.xml @@ -0,0 +1,34 @@ + + + + + + + UPDATE + user_account + SET + status = 1, + lockTime = CURRENT_TIMESTAMP + WHERE + username = #{username, jdbcType=VARCHAR} + + + UPDATE + user_account + SET + status = 0, + lockTime = 0 + WHERE + username = #{username, jdbcType=VARCHAR} + + + UPDATE + user_account + SET + lastLoginTime = CURRENT_TIMESTAMP + WHERE + username = #{username, jdbcType=VARCHAR} + + \ No newline at end of file diff --git a/src/test/java/com/cmcc/hy/phoenix/mapper/UserAccountMapperTest.java b/src/test/java/com/cmcc/hy/phoenix/mapper/UserAccountMapperTest.java index bade627a..ffb39d1f 100644 --- a/src/test/java/com/cmcc/hy/phoenix/mapper/UserAccountMapperTest.java +++ b/src/test/java/com/cmcc/hy/phoenix/mapper/UserAccountMapperTest.java @@ -1,5 +1,6 @@ package com.cmcc.hy.phoenix.mapper; +import com.cmcc.hy.phoenix.common.ConstValue; import com.cmcc.hy.phoenix.pojo.entity.UserAccount; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -27,7 +28,7 @@ public class UserAccountMapperTest { private UserAccountMapper userAccountMapper; @Test - public void getUserByName() throws JsonProcessingException { + public void getUserByNameUsedDefaultMapper() throws JsonProcessingException { Example exp = new Example(UserAccount.class); exp.createCriteria().andEqualTo("username", "admin"); @@ -38,4 +39,40 @@ public class UserAccountMapperTest { Assert.assertEquals(users.size(), 1); } + + @Test + public void getUserByName() throws JsonProcessingException { + UserAccount user = userAccountMapper.getUserByName("admin"); + + log.info(objMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user)); + + Assert.assertNotNull(user); + } + + @Test + public void lockUser() throws JsonProcessingException { + userAccountMapper.lockUserAccount("admin"); + + UserAccount user = userAccountMapper.getUserByName("admin"); + Assert.assertEquals(new Long(user.getStatus()), new Long(ConstValue.UserAccountStatus.LOCKED)); + log.info(objMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user)); + } + + @Test + public void unlockUser() throws JsonProcessingException { + userAccountMapper.unlockUserAccount("admin"); + + UserAccount user = userAccountMapper.getUserByName("admin"); + Assert.assertEquals(new Long(user.getStatus()), new Long(ConstValue.UserAccountStatus.NORMAL)); + log.info(objMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user)); + } + + @Test + public void refreshLoginTime() throws JsonProcessingException { + userAccountMapper.refreshLoginTime("admin"); + + UserAccount user = userAccountMapper.getUserByName("admin"); + Assert.assertNotNull(user); + log.info(objMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user)); + } }