diff --git a/src/main/java/com/dispose/common/ConstValue.java b/src/main/java/com/dispose/common/ConstValue.java index b8870b39..cf4f4ede 100644 --- a/src/main/java/com/dispose/common/ConstValue.java +++ b/src/main/java/com/dispose/common/ConstValue.java @@ -40,7 +40,7 @@ public class ConstValue { /** * The constant VERSION. */ - public static final int VERSION = 2; + public static final int VERSION = 3; /** * The constant CRYPTO_NONE. */ diff --git a/src/main/java/com/dispose/controller/AuthController.java b/src/main/java/com/dispose/controller/AuthController.java new file mode 100644 index 00000000..df0e4632 --- /dev/null +++ b/src/main/java/com/dispose/controller/AuthController.java @@ -0,0 +1,48 @@ +package com.dispose.controller; + +import com.dispose.common.ErrorCode; +import com.dispose.pojo.dto.protocol.auth.LoginReq; +import com.dispose.pojo.dto.protocol.auth.LoginRsp; +import com.dispose.pojo.dto.protocol.base.ProtocolReqDTO; +import com.dispose.pojo.dto.protocol.base.ProtocolRespDTO; +import com.dispose.service.UserAccountService; +import com.fasterxml.jackson.core.JsonProcessingException; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Controller; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import javax.validation.Valid; + +/** + * The type Auth controller. + * + * @author + */ +@Controller +@RequestMapping(value = "/auth") +@Slf4j +@Api(value = "处置平台认证接口", tags = "处置平台认证接口") +@Component +@Validated +public class AuthController { + @Resource + private UserAccountService userAccountService; + + @PostMapping("/login") + @ResponseBody + @ApiOperation("登录") + public ProtocolRespDTO userLogin(@RequestBody @Valid ProtocolReqDTO mr) throws JsonProcessingException { + return ProtocolRespDTO.result(ErrorCode.ERR_OK, + LoginRsp.builder() + .token("1234576") + .build()); + } +} diff --git a/src/main/java/com/dispose/exception/GlobalExceptionHandler.java b/src/main/java/com/dispose/exception/GlobalExceptionHandler.java new file mode 100644 index 00000000..2f4b2f9d --- /dev/null +++ b/src/main/java/com/dispose/exception/GlobalExceptionHandler.java @@ -0,0 +1,48 @@ +package com.dispose.exception; + +import com.dispose.common.ErrorCode; +import com.dispose.pojo.dto.protocol.base.BaseRespStatus; +import com.dispose.pojo.dto.protocol.base.ProtocolRespDTO; +import jodd.net.HttpStatus; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * The type Global exception handler. + * + * @author + */ +@ControllerAdvice +@Slf4j +public class GlobalExceptionHandler { + + /** + * Handle exception protocol resp dto. + * + * @param ex the ex + * @return the protocol resp dto + */ + @ExceptionHandler(MethodArgumentNotValidException.class) + @ResponseBody + public ProtocolRespDTO handleException(MethodArgumentNotValidException ex) { + log.error("Exception: {}", ex.getMessage()); + List exMsg = new ArrayList<>(); + + AtomicInteger idx = new AtomicInteger(); + + ex.getBindingResult() + .getAllErrors() + .forEach(v -> exMsg.add(idx.getAndIncrement() + ": " + v.getDefaultMessage())); + + return ProtocolRespDTO.result(ErrorCode.ERR_PARAMEXCEPTION, + HttpStatus.error400().status(), + exMsg.toArray(new String[0])); + } +} diff --git a/src/main/java/com/dispose/manager/UserAccountManager.java b/src/main/java/com/dispose/manager/UserAccountManager.java index 35e0a112..7fccb20f 100644 --- a/src/main/java/com/dispose/manager/UserAccountManager.java +++ b/src/main/java/com/dispose/manager/UserAccountManager.java @@ -122,4 +122,13 @@ public interface UserAccountManager { * @return the error code */ ErrorCode verifyTokenPermission(String token); + + /** + * Verify user login error code. + * + * @param username the username + * @param token the token + * @return the error code + */ + ErrorCode verifyUserLogin(String username, String token); } diff --git a/src/main/java/com/dispose/manager/impl/UserAccountManagerImpl.java b/src/main/java/com/dispose/manager/impl/UserAccountManagerImpl.java index 87e57e1d..eaff26c5 100644 --- a/src/main/java/com/dispose/manager/impl/UserAccountManagerImpl.java +++ b/src/main/java/com/dispose/manager/impl/UserAccountManagerImpl.java @@ -68,7 +68,7 @@ public class UserAccountManagerImpl implements UserAccountManager { public UserAccount getUserByName(String username) { // 根据用户名在缓存中查找用户 Optional findRet = userAccountCache.values().stream() - .filter(userAccountCache -> username.equals(userAccountCache.getUsername())) + .filter(userAccountCache -> userAccountCache.getUsername().equals(username)) .findFirst(); return findRet.orElseGet(() -> userAccountMapper.getUserByName(username)); @@ -401,6 +401,49 @@ public class UserAccountManagerImpl implements UserAccountManager { return ErrorCode.ERR_PERMISSION; } + /** + * Verify user login error code. + * + * @param username the username + * @param token the token + * @return the error code + */ + @Override + public ErrorCode verifyUserLogin(String username, String token) { + UserAccount user; + + // 本机曾经登录过 + if (userAccountCache.containsKey(token)) { + user = userAccountCache.get(token); + + // 超时 + if(tokenTimeout(user.getLastAccess())) { + return ErrorCode.ERR_TOKENTIMEOUT; + } + + return ErrorCode.ERR_OK; + + } else { + user = userAccountMapper.getUserByToken(token); + + // 用户未登录或者已经注销 + if(user == null) { + return ErrorCode.ERR_LOGOUT; + } + + // 用户未登录或者已经注销 + if(user.getToken().length() == 0) { + return ErrorCode.ERR_LOGOUT; + } + + if(tokenTimeout(user.getLastAccess())) { + return ErrorCode.ERR_TOKENTIMEOUT; + } + + return ErrorCode.ERR_OK; + } + } + /** * Token timeout boolean. * diff --git a/src/main/java/com/dispose/mapper/UserAccountMapper.java b/src/main/java/com/dispose/mapper/UserAccountMapper.java index 22c63e01..d1615fb8 100644 --- a/src/main/java/com/dispose/mapper/UserAccountMapper.java +++ b/src/main/java/com/dispose/mapper/UserAccountMapper.java @@ -78,9 +78,8 @@ public interface UserAccountMapper extends Mapper, * Upgrade login time string. * * @param username the username - * @return the string */ - String upgradeLoginTime(@Param("username") String username); + void upgradeLoginTime(@Param("username") String username); /** * Upgrade last access time string. diff --git a/src/main/java/com/dispose/pojo/dto/protocol/auth/LoginReq.java b/src/main/java/com/dispose/pojo/dto/protocol/auth/LoginReq.java new file mode 100644 index 00000000..ce3bfb24 --- /dev/null +++ b/src/main/java/com/dispose/pojo/dto/protocol/auth/LoginReq.java @@ -0,0 +1,34 @@ +package com.dispose.pojo.dto.protocol.auth; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; + +/** + * The type Login info. + * + * @author + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@JsonInclude(JsonInclude.Include.NON_NULL) +public class LoginReq { + /** + * The User name. + */ + @NotBlank(message = "userName 用户名不能为空") + private String userName; + /** + * The Password. + */ + @NotBlank(message = "password 密码不能为空") + @Length(min = 64, max = 64, message = "password 密码长度必须为SHA256编码后的长度") + private String password; +} diff --git a/src/main/java/com/dispose/pojo/dto/protocol/auth/LoginRsp.java b/src/main/java/com/dispose/pojo/dto/protocol/auth/LoginRsp.java new file mode 100644 index 00000000..cd8f4208 --- /dev/null +++ b/src/main/java/com/dispose/pojo/dto/protocol/auth/LoginRsp.java @@ -0,0 +1,44 @@ +package com.dispose.pojo.dto.protocol.auth; + +import com.dispose.pojo.dto.protocol.base.BaseRespStatus; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * The type Login rsp. + * + * @author + */ +@EqualsAndHashCode(callSuper = true) +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({"userName", "token", "logTime", "expireTime", "status", "message"}) +public class LoginRsp extends BaseRespStatus { + + /** + * The User name. + */ + private String userName; + + /** + * The Token. + */ + private String token; + + /** + * The Log time. + */ + private Long logTime; + /** + * The Expire time. + */ + private Long expireTime; +} diff --git a/src/main/java/com/dispose/pojo/dto/protocol/base/BaseProtocolDTO.java b/src/main/java/com/dispose/pojo/dto/protocol/base/BaseProtocolDTO.java new file mode 100644 index 00000000..c10cdf54 --- /dev/null +++ b/src/main/java/com/dispose/pojo/dto/protocol/base/BaseProtocolDTO.java @@ -0,0 +1,47 @@ +package com.dispose.pojo.dto.protocol.base; + +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Range; + +import javax.validation.Valid; +import javax.validation.constraints.DecimalMin; +import javax.validation.constraints.NotNull; + +/** + * The type Base protocol dto. + * + * @author + */ +@Data +@NoArgsConstructor +@ApiModel("通信协议实体") +@JsonPropertyOrder({"ver", "cryptoType", "timeStamp", "msgContent"}) +public class BaseProtocolDTO { + @ApiModelProperty(value = "协议版本号", required = true, example = "1") + @NotNull(message = "ver 字段不能为空") + @Range(min = 3, max = 9999, message = "ver 字段最小值为 3") + private Integer ver; + + @ApiModelProperty(value = "msgContent字段内容编码格式:\n" + + "0:无编码格式,普通字符串\n" + + "1:base64编码格式\n" + + "2:采用AES加密后的base64编码格式\n", required = true, + allowableValues = "0, 1, 2", + example = "0") + @NotNull(message = "cryptoType 字段不能为空") + @Range(min = 0, max = 2, message = "cryptoType 字段取值为 [0, 2]") + private Integer cryptoType; + + @ApiModelProperty(value = "当前UTC时间戳", required = true, example = "1526625689000") + @NotNull(message = "timeStamp 字段不能为空") + @DecimalMin(value = "1595494343000", message = "timeStamp 字段值不能为过去时间") + private Long timeStamp; + + @ApiModelProperty(value = "协议详细内容\n", example = "{}") + @Valid + private T msgContent; +} diff --git a/src/main/java/com/dispose/pojo/dto/protocol/base/BaseRespStatus.java b/src/main/java/com/dispose/pojo/dto/protocol/base/BaseRespStatus.java new file mode 100644 index 00000000..4d1c6291 --- /dev/null +++ b/src/main/java/com/dispose/pojo/dto/protocol/base/BaseRespStatus.java @@ -0,0 +1,37 @@ +package com.dispose.pojo.dto.protocol.base; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Arrays; + +/** + * The type Response status. + * + * @author + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class BaseRespStatus { + + /** + * The Status. + */ + private Integer status; + /** + * The Message. + */ + private String[] message; + + /** + * To string string. + * + * @return the string + */ + @Override + public String toString() { + return "{\"status\":" + status + ", \"message\":\"" + Arrays.toString(message) + "\"}"; + } +} diff --git a/src/main/java/com/dispose/pojo/dto/protocol/base/ProtocolReqDTO.java b/src/main/java/com/dispose/pojo/dto/protocol/base/ProtocolReqDTO.java new file mode 100644 index 00000000..ec0c4b72 --- /dev/null +++ b/src/main/java/com/dispose/pojo/dto/protocol/base/ProtocolReqDTO.java @@ -0,0 +1,16 @@ +package com.dispose.pojo.dto.protocol.base; + +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; + +/** + * The type Protocol req dto. + * + * @author + */ +@NoArgsConstructor +@ToString +@Slf4j +public class ProtocolReqDTO extends BaseProtocolDTO { +} diff --git a/src/main/java/com/dispose/pojo/dto/protocol/base/ProtocolRespDTO.java b/src/main/java/com/dispose/pojo/dto/protocol/base/ProtocolRespDTO.java new file mode 100644 index 00000000..f16816ec --- /dev/null +++ b/src/main/java/com/dispose/pojo/dto/protocol/base/ProtocolRespDTO.java @@ -0,0 +1,113 @@ +package com.dispose.pojo.dto.protocol.base; + +import com.dispose.common.ConstValue; +import com.dispose.common.ErrorCode; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * The type Protocol resp dto. + * + * @param the type parameter + * @author + */ +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +@JsonPropertyOrder({"ver", "cryptoType", "timeStamp", "code", "msgContent"}) +public class ProtocolRespDTO extends BaseProtocolDTO { + /** + * The constant OBJECT_MAPPER. + */ + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + /** + * The Code. + */ + @ApiModelProperty(value = "服务器返回状态码", example = "200") + private Integer code; + + /** + * Result protocol resp dto. + * + * @param the type parameter + * @param err the err + * @param obj the obj + * @return the protocol resp dto + */ + public static ProtocolRespDTO result(ErrorCode err, T obj) { + return result(err, obj, ConstValue.Protocol.CRYPTO_NONE); + } + + /** + * Result protocol resp dto. + * + * @param the type parameter + * @param err the err + * @param respMsg the resp msg + * @param crypto the crypto + * @return the protocol resp dto + */ + public static ProtocolRespDTO result(ErrorCode err, T respMsg, Integer crypto) { + ProtocolRespDTO resp = new ProtocolRespDTO<>(); + + resp.setVer(ConstValue.Protocol.VERSION); + resp.setCode(err.getHttpCode()); + resp.setCryptoType(ConstValue.Protocol.CRYPTO_NONE); + resp.setTimeStamp(System.currentTimeMillis()); + resp.setMsgContent(respMsg); + + return resp; + } + + /** + * Result protocol resp dto. + * + * @param err the err + * @return the protocol resp dto + */ + public static ProtocolRespDTO result(ErrorCode err) { + + ProtocolRespDTO resp = new ProtocolRespDTO<>(); + BaseRespStatus rspMsg = new BaseRespStatus(); + rspMsg.setStatus(err.getCode()); + rspMsg.setMessage(new String[] {err.getMsg()}); + + resp.setVer(ConstValue.Protocol.VERSION); + resp.setCode(err.getHttpCode()); + resp.setCryptoType(ConstValue.Protocol.CRYPTO_NONE); + resp.setTimeStamp(System.currentTimeMillis()); + resp.setMsgContent(rspMsg); + + return resp; + } + + /** + * Result protocol resp dto. + * + * @param errCode the err code + * @param httpCode the http code + * @param message the message + * @return the protocol resp dto + */ + public static ProtocolRespDTO result(ErrorCode errCode, Integer httpCode, String[] message) { + ProtocolRespDTO resp = new ProtocolRespDTO<>(); + BaseRespStatus rspMsg = new BaseRespStatus(); + rspMsg.setStatus(errCode.getCode()); + rspMsg.setMessage(message); + + resp.setVer(ConstValue.Protocol.VERSION); + resp.setCode(httpCode); + resp.setCryptoType(ConstValue.Protocol.CRYPTO_NONE); + resp.setTimeStamp(System.currentTimeMillis()); + resp.setMsgContent(rspMsg); + + return resp; + } +} diff --git a/src/main/java/com/dispose/service/impl/UserAccountServiceImpl.java b/src/main/java/com/dispose/service/impl/UserAccountServiceImpl.java index 3a4ae4f0..5b37f485 100644 --- a/src/main/java/com/dispose/service/impl/UserAccountServiceImpl.java +++ b/src/main/java/com/dispose/service/impl/UserAccountServiceImpl.java @@ -121,10 +121,12 @@ public class UserAccountServiceImpl implements UserAccountService { return ErrorCode.ERR_USERNOTFOUND; } + ErrorCode err = userAccountManager.verifyUserLogin(username, token); + // 注销 userAccountManager.cleanUserToken(username); - return ErrorCode.ERR_OK; + return err; } /** diff --git a/src/main/resources/mappers/UserAccount.xml b/src/main/resources/mappers/UserAccount.xml index 48e5ac93..9cabfbad 100644 --- a/src/main/resources/mappers/UserAccount.xml +++ b/src/main/resources/mappers/UserAccount.xml @@ -41,16 +41,12 @@ WHERE username = #{username, jdbcType=VARCHAR} - +