登录/登出接口完善
This commit is contained in:
+3
-1
@@ -36,7 +36,9 @@ public enum ExceptionConstant {
|
||||
USER_NOT_LOGIN(1, "用户未登录"),
|
||||
PARAMS_INVALID(2, "参数不正确"),
|
||||
PARAMS_NOT_NULL(3, "参数[%s]不能为空"),
|
||||
SYSTEM_ERROR(500, "系统异常");
|
||||
USER_NAME_OR_PASSWORD_ERROR(4, "用户名或密码错误"),
|
||||
SYSTEM_ERROR(500, "系统异常"),
|
||||
;
|
||||
|
||||
private int code;
|
||||
private String msg;
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2022 aoshiguchen
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package fun.asgc.neutrino.proxy.server.base.rest;
|
||||
|
||||
import fun.asgc.neutrino.proxy.server.dal.entity.UserDO;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author: aoshiguchen
|
||||
* @date: 2022/8/2
|
||||
*/
|
||||
public class SystemContextHolder {
|
||||
private static final ThreadLocal<UserDO> userHolder = new ThreadLocal<>();
|
||||
private static final ThreadLocal<String> tokenHolder = new ThreadLocal<>();
|
||||
|
||||
public static void remove() {
|
||||
userHolder.remove();
|
||||
tokenHolder.remove();
|
||||
}
|
||||
|
||||
public static void setUser(UserDO user) {
|
||||
userHolder.set(user);
|
||||
}
|
||||
|
||||
public static UserDO getUser() {
|
||||
return userHolder.get();
|
||||
}
|
||||
|
||||
public static void setToken(String token) {
|
||||
tokenHolder.set(token);
|
||||
}
|
||||
|
||||
public static String getToken() {
|
||||
return tokenHolder.get();
|
||||
}
|
||||
}
|
||||
+26
-1
@@ -21,9 +21,17 @@
|
||||
*/
|
||||
package fun.asgc.neutrino.proxy.server.base.rest.interceptor;
|
||||
|
||||
import fun.asgc.neutrino.core.util.BeanManager;
|
||||
import fun.asgc.neutrino.core.util.StringUtil;
|
||||
import fun.asgc.neutrino.core.web.context.HttpRequestWrapper;
|
||||
import fun.asgc.neutrino.core.web.context.HttpResponseWrapper;
|
||||
import fun.asgc.neutrino.core.web.interceptor.HandlerInterceptor;
|
||||
import fun.asgc.neutrino.proxy.server.base.rest.Authorization;
|
||||
import fun.asgc.neutrino.proxy.server.base.rest.ExceptionConstant;
|
||||
import fun.asgc.neutrino.proxy.server.base.rest.ServiceException;
|
||||
import fun.asgc.neutrino.proxy.server.base.rest.SystemContextHolder;
|
||||
import fun.asgc.neutrino.proxy.server.dal.entity.UserDO;
|
||||
import fun.asgc.neutrino.proxy.server.service.UserService;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@@ -36,8 +44,25 @@ public class BaseAuthInterceptor implements HandlerInterceptor {
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpRequestWrapper requestParser, HttpResponseWrapper responseWrapper, String route, Method targetMethod) throws Exception {
|
||||
// TODO
|
||||
Authorization authorization = targetMethod.getAnnotation(Authorization.class);
|
||||
if (null == authorization || authorization.login()) {
|
||||
String authorize = requestParser.getHeaderValue("Authorize");
|
||||
if (StringUtil.isEmpty(authorize)) {
|
||||
throw ServiceException.create(ExceptionConstant.USER_NOT_LOGIN);
|
||||
}
|
||||
UserDO userDO = BeanManager.getBean(UserService.class).findByToken(authorize);
|
||||
if (null == userDO) {
|
||||
throw ServiceException.create(ExceptionConstant.USER_NOT_LOGIN);
|
||||
}
|
||||
SystemContextHolder.setUser(userDO);
|
||||
SystemContextHolder.setToken(authorize);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpRequestWrapper requestParser, HttpResponseWrapper responseWrapper, String route, Method targetMethod) {
|
||||
SystemContextHolder.remove();
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -57,9 +57,8 @@ public class IndexController {
|
||||
}
|
||||
|
||||
@PostMapping("logout")
|
||||
public LogoutRes logout(@RequestBody LogoutReq req) {
|
||||
// TODO
|
||||
return null;
|
||||
public void logout() {
|
||||
userService.logout();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2022 aoshiguchen
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package fun.asgc.neutrino.proxy.server.dal;
|
||||
|
||||
import fun.asgc.neutrino.core.annotation.Component;
|
||||
import fun.asgc.neutrino.core.db.annotation.Insert;
|
||||
import fun.asgc.neutrino.core.db.mapper.SqlMapper;
|
||||
import fun.asgc.neutrino.proxy.server.dal.entity.UserLoginRecordDO;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author: aoshiguchen
|
||||
* @date: 2022/8/2
|
||||
*/
|
||||
@Component
|
||||
public interface UserLoginRecordMapper extends SqlMapper {
|
||||
/**
|
||||
* 新增用户登录日志
|
||||
* @param userLoginRecord
|
||||
* @return
|
||||
*/
|
||||
@Insert("insert into `user_login_record`(`user_id`,`ip`,`token`,`type`,`create_time`) values(:userId,:ip,:token,:type,:createTime)")
|
||||
int add(UserLoginRecordDO userLoginRecord);
|
||||
}
|
||||
@@ -42,4 +42,12 @@ public interface UserMapper extends SqlMapper {
|
||||
@Select("select * from user where login_name = ?")
|
||||
UserDO findByLoginName(String loginName);
|
||||
|
||||
/**
|
||||
* 根据id查询单条记录
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@Select("select * from user where id = ?")
|
||||
UserDO findById(Integer id);
|
||||
|
||||
}
|
||||
|
||||
+19
@@ -22,10 +22,14 @@
|
||||
package fun.asgc.neutrino.proxy.server.dal;
|
||||
|
||||
import fun.asgc.neutrino.core.annotation.Component;
|
||||
import fun.asgc.neutrino.core.db.annotation.Delete;
|
||||
import fun.asgc.neutrino.core.db.annotation.Insert;
|
||||
import fun.asgc.neutrino.core.db.annotation.Select;
|
||||
import fun.asgc.neutrino.core.db.mapper.SqlMapper;
|
||||
import fun.asgc.neutrino.proxy.server.dal.entity.UserTokenDO;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author: aoshiguchen
|
||||
@@ -40,4 +44,19 @@ public interface UserTokenMapper extends SqlMapper {
|
||||
*/
|
||||
@Insert("insert into `user_token`(`token`,`user_id`,`expiration_time`,`create_time`,`update_time`) values (:token,:userId,:expirationTime,:createTime,:updateTime)")
|
||||
int add(UserTokenDO userToken);
|
||||
|
||||
/**
|
||||
* 根据token查询单条记录
|
||||
* @param token
|
||||
* @return
|
||||
*/
|
||||
@Select("select * from user_token where token = ? and expiration_time > ?")
|
||||
UserTokenDO findByAvailableToken(String token, Long time);
|
||||
|
||||
/**
|
||||
* 根据token删除记录
|
||||
* @param token
|
||||
*/
|
||||
@Delete("delete from user_token where token = ?")
|
||||
void deleteByToken(String token);
|
||||
}
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Copyright (C) 2018-2022 Zeyi information technology (Shanghai) Co., Ltd.
|
||||
* <p>
|
||||
* All right reserved.
|
||||
* <p>
|
||||
* This software is the confidential and proprietary
|
||||
* information of Zeyi Company of China.
|
||||
* ("Confidential Information"). You shall not disclose
|
||||
* such Confidential Information and shall use it only
|
||||
* in accordance with the terms of the contract agreement
|
||||
* you entered into with Zeyi inc.
|
||||
*/
|
||||
package fun.asgc.neutrino.proxy.server.dal.entity;
|
||||
|
||||
import fun.asgc.neutrino.core.db.annotation.Id;
|
||||
import fun.asgc.neutrino.core.db.annotation.Table;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author: aoshiguchen
|
||||
* @date: 2022/8/2
|
||||
*/
|
||||
@ToString
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Table("user_login_record")
|
||||
public class UserLoginRecordDO {
|
||||
/**
|
||||
* 类型 - 登录
|
||||
*/
|
||||
public static final Integer TYPE_LOGIN = 1;
|
||||
/**
|
||||
* 类型 - 登出
|
||||
*/
|
||||
public static final Integer TYPE_LOGOUT = 2;
|
||||
|
||||
@Id
|
||||
private Integer id;
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Integer userId;
|
||||
/**
|
||||
* token
|
||||
*/
|
||||
private String token;
|
||||
/**
|
||||
* ip
|
||||
*/
|
||||
private String ip;
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private Integer type;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
}
|
||||
+37
-5
@@ -23,15 +23,21 @@ package fun.asgc.neutrino.proxy.server.service;
|
||||
|
||||
import fun.asgc.neutrino.core.annotation.Autowired;
|
||||
import fun.asgc.neutrino.core.annotation.Component;
|
||||
import fun.asgc.neutrino.core.web.annotation.RequestBody;
|
||||
import fun.asgc.neutrino.core.util.DateUtil;
|
||||
import fun.asgc.neutrino.proxy.server.base.rest.ExceptionConstant;
|
||||
import fun.asgc.neutrino.proxy.server.base.rest.ServiceException;
|
||||
import fun.asgc.neutrino.proxy.server.base.rest.SystemContextHolder;
|
||||
import fun.asgc.neutrino.proxy.server.controller.req.LoginReq;
|
||||
import fun.asgc.neutrino.proxy.server.controller.res.LoginRes;
|
||||
import fun.asgc.neutrino.proxy.server.dal.UserLoginRecordMapper;
|
||||
import fun.asgc.neutrino.proxy.server.dal.UserMapper;
|
||||
import fun.asgc.neutrino.proxy.server.dal.UserTokenMapper;
|
||||
import fun.asgc.neutrino.proxy.server.dal.entity.UserDO;
|
||||
import fun.asgc.neutrino.proxy.server.dal.entity.UserLoginRecordDO;
|
||||
import fun.asgc.neutrino.proxy.server.dal.entity.UserTokenDO;
|
||||
import fun.asgc.neutrino.proxy.server.util.Md5Util;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -46,25 +52,36 @@ public class UserService {
|
||||
private UserMapper userMapper;
|
||||
@Autowired
|
||||
private UserTokenMapper userTokenMapper;
|
||||
@Autowired
|
||||
private UserLoginRecordMapper userLoginRecordMapper;
|
||||
|
||||
public LoginRes login(LoginReq req) {
|
||||
UserDO userDO = userMapper.findByLoginName(req.getLoginName());
|
||||
if (null == userDO || !Md5Util.encode(req.getLoginPassword()).equals(userDO.getLoginPassword())) {
|
||||
// TODO 抛出异常
|
||||
throw ServiceException.create(ExceptionConstant.USER_NAME_OR_PASSWORD_ERROR);
|
||||
}
|
||||
String token = UUID.randomUUID().toString().replaceAll("-", "");
|
||||
|
||||
Date now = new Date();
|
||||
// TODO 计算过期时间
|
||||
Date expirationTime = DateUtil.addDate(now, Calendar.HOUR, 1);
|
||||
|
||||
// 缓存token
|
||||
userTokenMapper.add(new UserTokenDO()
|
||||
.setToken(token)
|
||||
.setUserId(userDO.getId())
|
||||
.setExpirationTime(now)
|
||||
.setExpirationTime(expirationTime)
|
||||
.setCreateTime(now)
|
||||
.setUpdateTime(now)
|
||||
);
|
||||
|
||||
// TODO 新增登录日志
|
||||
// 新增用户登录日志
|
||||
userLoginRecordMapper.add(new UserLoginRecordDO()
|
||||
.setUserId(userDO.getId())
|
||||
.setIp("111")
|
||||
.setToken(token)
|
||||
.setType(UserLoginRecordDO.TYPE_LOGIN)
|
||||
.setCreateTime(now)
|
||||
);
|
||||
|
||||
return new LoginRes()
|
||||
.setToken(token)
|
||||
@@ -72,4 +89,19 @@ public class UserService {
|
||||
.setUserName(userDO.getName());
|
||||
}
|
||||
|
||||
public void logout() {
|
||||
userTokenMapper.deleteByToken(SystemContextHolder.getToken());
|
||||
}
|
||||
|
||||
public UserDO findByToken(String token) {
|
||||
Date now = new Date();
|
||||
UserTokenDO userTokenDO = userTokenMapper.findByAvailableToken(token, now.getTime());
|
||||
if (null == userTokenDO) {
|
||||
return null;
|
||||
}
|
||||
UserDO userDO = userMapper.findById(userTokenDO.getUserId());
|
||||
// TODO 校验用户是否已被禁用
|
||||
return userDO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user