REM:
1. 用户管理功能开发过程保存
2. 用户管理相关单元测试用例
This commit is contained in:
HuangXin 2020-07-22 17:53:01 +08:00
parent d1296b4d1a
commit 1779808d72
17 changed files with 1079 additions and 137 deletions

View File

@ -60,30 +60,4 @@ public class ConstValue {
public static final int REQUEST_TIMEOUT_MS = 10 * 1000; public static final int REQUEST_TIMEOUT_MS = 10 * 1000;
} }
/**
* The type User account status.
*
* @author <huangxin@cmhi.chinamoblie.com>
*/
public static class UserAccountStatus {
/**
* The constant NORMAL.
*/
public static final int NORMAL = 0;
/**
* The constant LOCKED.
*/
public static final int LOCKED = 1;
/**
* The constant DISABLED.
*/
public static final int DISABLED = 2;
/**
* The constant DELETED.
*/
public static final int DELETED = 3;
}
} }

View File

@ -148,14 +148,26 @@ public enum ErrorCode {
ERR_UNABLEDISPOSEIP(33, "无法处置该IP"), ERR_UNABLEDISPOSEIP(33, "无法处置该IP"),
/** /**
* Err haohan error error code. * The Err haohan error.
*/ */
ERR_HAOHAN_ERROR(34, "浩瀚设备返回错误"), ERR_HAOHAN_ERROR(34, "浩瀚设备返回错误"),
; ;
/**
* The Errno.
*/
private final int errno; private final int errno;
/**
* The Err msg.
*/
private final String errMsg; private final String errMsg;
/**
* Instantiates a new Error code.
*
* @param err the err
* @param msg the msg
*/
ErrorCode(int err, String msg) { ErrorCode(int err, String msg) {
this.errno = err; this.errno = err;
this.errMsg = msg; this.errMsg = msg;

View File

@ -31,8 +31,8 @@ public class Helper {
* @param dateTime the date time * @param dateTime the date time
* @return the timestamp milli second * @return the timestamp milli second
*/ */
public static int getTimestampMilliSecond(String dateTime) { public static long getTimestampMilliSecond(String dateTime) {
return (int)(Timestamp.valueOf(dateTime).toInstant().toEpochMilli()); return Timestamp.valueOf(dateTime).toInstant().toEpochMilli();
} }
/** /**

View File

@ -0,0 +1,63 @@
package com.dispose.common;
/**
* The enum User account status.
*
* @author <huangxin@cmhi.chinamoblie.com>
*/
public enum UserAccountStatus {
/**
* Normal user account status.
*/
NORMAL(0, "正常"),
/**
* Locked user account status.
*/
LOCKED(1, "锁定"),
/**
* Disabled user account status.
*/
DISABLED(2, "禁用"),
/**
* Deleted user account status.
*/
DELETED(3, "删除");
/**
* The Code.
*/
private final int code;
/**
* The Readme.
*/
private final String readme;
/**
* Instantiates a new User account status.
*
* @param code the code
* @param readme the readme
*/
UserAccountStatus(int code, String readme) {
this.code = code;
this.readme = readme;
}
/**
* Gets code.
*
* @return the code
*/
public int getCode() {
return this.code;
}
/**
* Gets readme.
*
* @return the readme
*/
public String getReadme() {
return this.readme;
}
}

View File

@ -15,7 +15,16 @@ import org.springframework.stereotype.Component;
@Component @Component
@ConfigurationProperties(prefix = "dispose") @ConfigurationProperties(prefix = "dispose")
public class DisposeConfigure { public class DisposeConfigure {
/**
* The Check protocol timeout.
*/
private String checkProtocolTimeout; private String checkProtocolTimeout;
/**
* The Check request token.
*/
private String checkRequestToken; private String checkRequestToken;
private String checkAdminPermission; /**
* The Split char.
*/
private String splitChar;
} }

View File

@ -0,0 +1,26 @@
package com.dispose.config;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* The type User permission configure.
*
* @author <huangxin@cmhi.chinamoblie.com>
*/
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "permission")
public class UserPermissionConfigure {
/**
* The Admin users.
*/
private String adminUsers;
/**
* The Admin check.
*/
private String adminCheck;
}

View File

@ -1,16 +1,33 @@
package com.dispose.manager; package com.dispose.manager;
import com.dispose.common.ErrorCode; import com.dispose.common.ErrorCode;
import com.dispose.pojo.po.MulReturnType; import com.dispose.pojo.entity.UserAccount;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
/** /**
* The interface User account cache manager. * The interface User account manager.
* *
* @author <huangxin@cmhi.chinamoblie.com> * @author <huangxin@cmhi.chinamoblie.com>
*/ */
public interface UserAccountManager { public interface UserAccountManager {
/**
* Gets user by name.
*
* @param username the username
* @return the user by name
*/
UserAccount getUserByName(String username);
/**
* Gets user by token.
*
* @param token the token
* @return the user by token
*/
UserAccount getUserByToken(String token);
/** /**
* Gets user token. * Gets user token.
* *
@ -18,7 +35,7 @@ public interface UserAccountManager {
* @return the user token * @return the user token
* @throws NoSuchAlgorithmException the no such algorithm exception * @throws NoSuchAlgorithmException the no such algorithm exception
*/ */
MulReturnType<ErrorCode, String> getUserToken(String username) throws NoSuchAlgorithmException; String getUserToken(String username) throws NoSuchAlgorithmException;
/** /**
* Gets usr pwd err times. * Gets usr pwd err times.
@ -43,15 +60,6 @@ public interface UserAccountManager {
*/ */
void cleanUserToken(String username); void cleanUserToken(String username);
/**
* Verify user login error code.
*
* @param username the username
* @param token the token
* @return the error code
*/
ErrorCode verifyUserLogin(String username, String token);
/** /**
* Verify token error code. * Verify token error code.
* *
@ -61,18 +69,57 @@ public interface UserAccountManager {
ErrorCode verifyToken(String token); ErrorCode verifyToken(String token);
/** /**
* Gets username by token. * Lock user account.
* *
* @param token the token * @param username the username
* @return the username by token
*/ */
String getUsernameByToken(String token); void lockUserAccount(String username);
/** /**
* Verify permission error code. * Unlock user account.
*
* @param username the username
*/
void unlockUserAccount(String username);
/**
* Upgrade login time.
*
* @param username the username
*/
void upgradeLoginTime(String username);
/**
* Create user account user account.
*
* @param username the username
* @param password the password
* @param operators the operators
* @return the user account
*/
UserAccount createUserAccount(String username, String password, String operators);
/**
* Delete user account.
*
* @param username the username
* @param operators the operators
*/
void deleteUserAccount(String username, String operators);
/**
* Disable user account.
*
* @param username the username
* @param operators the operators
*/
void disableUserAccount(String username, String operators);
/**
* Verify token permission error code.
* *
* @param token the token * @param token the token
* @return the error code * @return the error code
*/ */
ErrorCode verifyPermission(String token); ErrorCode verifyTokenPermission(String token);
} }

View File

@ -4,10 +4,11 @@ import cn.hutool.core.convert.Convert;
import com.dispose.common.ConstValue; import com.dispose.common.ConstValue;
import com.dispose.common.ErrorCode; import com.dispose.common.ErrorCode;
import com.dispose.common.Helper; import com.dispose.common.Helper;
import com.dispose.config.DisposeConfigure;
import com.dispose.config.UserPermissionConfigure;
import com.dispose.manager.UserAccountManager; import com.dispose.manager.UserAccountManager;
import com.dispose.mapper.UserAccountMapper; import com.dispose.mapper.UserAccountMapper;
import com.dispose.pojo.entity.UserAccount; import com.dispose.pojo.entity.UserAccount;
import com.dispose.pojo.po.MulReturnType;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.binary.Hex;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -15,6 +16,7 @@ import org.springframework.stereotype.Component;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Optional; import java.util.Optional;
import java.util.Random; import java.util.Random;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -27,6 +29,12 @@ import java.util.concurrent.ConcurrentHashMap;
@Component @Component
@Slf4j @Slf4j
public class UserAccountManagerImpl implements UserAccountManager { public class UserAccountManagerImpl implements UserAccountManager {
/**
* The Admin users.
*/
private static String[] ADMIN_USERS;
/** /**
* The User account cache. * The User account cache.
*/ */
@ -38,6 +46,49 @@ public class UserAccountManagerImpl implements UserAccountManager {
@Resource @Resource
private UserAccountMapper userAccountMapper; private UserAccountMapper userAccountMapper;
/**
* The User permission configure.
*/
@Resource
private UserPermissionConfigure userPermissionConfigure;
/**
* The Dispose configure.
*/
@Resource
private DisposeConfigure disposeConfigure;
/**
* Gets user by name.
*
* @param username the username
* @return the user by name
*/
@Override
public UserAccount getUserByName(String username) {
// 根据用户名在缓存中查找用户
Optional<UserAccount> findRet = userAccountCache.values().stream()
.filter(userAccountCache -> username.equals(userAccountCache.getUsername()))
.findFirst();
return findRet.orElseGet(() -> userAccountMapper.getUserByName(username));
}
/**
* Gets user by token.
*
* @param token the token
* @return the user by token
*/
@Override
public UserAccount getUserByToken(String token) {
if (userAccountCache.containsKey(token)) {
return userAccountCache.get(token);
} else {
return userAccountMapper.getUserByToken(token);
}
}
/** /**
* Gets user token. * Gets user token.
* *
@ -46,7 +97,7 @@ public class UserAccountManagerImpl implements UserAccountManager {
* @throws NoSuchAlgorithmException the no such algorithm exception * @throws NoSuchAlgorithmException the no such algorithm exception
*/ */
@Override @Override
public MulReturnType<ErrorCode, String> getUserToken(String username) throws NoSuchAlgorithmException { public String getUserToken(String username) throws NoSuchAlgorithmException {
String token; String token;
UserAccount user; UserAccount user;
@ -79,21 +130,10 @@ public class UserAccountManagerImpl implements UserAccountManager {
// 更新访问时间 // 更新访问时间
user.setLastAccess(userAccountMapper.upgradeLastAccessTime(username)); user.setLastAccess(userAccountMapper.upgradeLastAccessTime(username));
return MulReturnType.<ErrorCode, String>builder()
.firstParam(ErrorCode.ERR_OK)
.secondParam(token)
.build();
} else { } else {
// 调用函数前确保用户一定存在
user = userAccountMapper.getUserByName(username); user = userAccountMapper.getUserByName(username);
// 用户不存在
if (user == null) {
log.error("User {} not exists", username);
return MulReturnType.<ErrorCode, String>builder()
.firstParam(ErrorCode.ERR_USERNOTFOUND)
.build();
}
// 超时或者以前未登录 // 超时或者以前未登录
if (tokenTimeout(user.getToken()) || user.getToken().length() == 0) { if (tokenTimeout(user.getToken()) || user.getToken().length() == 0) {
token = createUserToken(username); token = createUserToken(username);
@ -105,16 +145,15 @@ public class UserAccountManagerImpl implements UserAccountManager {
} }
// 更新访问时间 // 更新访问时间
userAccountMapper.upgradeLastAccessTime(username); user.setLastAccess(userAccountMapper.upgradeLastAccessTime(username));
// 更新用户token
user.setToken(token);
// 添加用户到缓存 // 添加用户到缓存
userAccountCache.put(token, user); userAccountCache.put(token, user);
return MulReturnType.<ErrorCode, String>builder()
.firstParam(ErrorCode.ERR_OK)
.secondParam(token)
.build();
} }
return token;
} }
/** /**
@ -125,7 +164,16 @@ public class UserAccountManagerImpl implements UserAccountManager {
*/ */
@Override @Override
public int getUsrPwdErrTimes(String username) { public int getUsrPwdErrTimes(String username) {
return 0; Optional<UserAccount> findRet = userAccountCache.values().stream()
.filter(userAccountCache -> username.equals(userAccountCache.getUsername()))
.findFirst();
if (findRet.isPresent()) {
return findRet.get().getPwdErrTimes();
} else {
// 调用函数前确保用户一定存在
return userAccountMapper.getUserByName(username).getPwdErrTimes();
}
} }
/** /**
@ -136,7 +184,16 @@ public class UserAccountManagerImpl implements UserAccountManager {
*/ */
@Override @Override
public void setUserPwdErrTimes(String username, Integer errTimes) { public void setUserPwdErrTimes(String username, Integer errTimes) {
Optional<UserAccount> findRet = userAccountCache.values().stream()
.filter(userAccountCache -> username.equals(userAccountCache.getUsername()))
.findFirst();
if (findRet.isPresent()) {
findRet.get().setPwdErrTimes(Math.abs(errTimes));
} else {
// 调用函数前确保用户一定存在
userAccountMapper.getUserByName(username).setPwdErrTimes(Math.abs(errTimes));
}
} }
/** /**
@ -146,19 +203,22 @@ public class UserAccountManagerImpl implements UserAccountManager {
*/ */
@Override @Override
public void cleanUserToken(String username) { public void cleanUserToken(String username) {
UserAccount user;
// 根据用户名在缓存中查找用户
Optional<UserAccount> findRet = userAccountCache.values().stream()
.filter(userAccountCache -> username.equals(userAccountCache.getUsername()))
.findFirst();
// 缓存中存在
if (findRet.isPresent()) {
user = findRet.get();
// 缓存中删除当前用户
userAccountCache.remove(user.getToken());
} }
/** // 清除数据库token
* Verify user login error code. userAccountMapper.upgradeToken(username, "");
*
* @param username the username
* @param token the token
* @return the error code
*/
@Override
public ErrorCode verifyUserLogin(String username, String token) {
return null;
} }
/** /**
@ -218,28 +278,6 @@ public class UserAccountManagerImpl implements UserAccountManager {
return ErrorCode.ERR_LOGOUT; return ErrorCode.ERR_LOGOUT;
} }
/**
* Gets username by token.
*
* @param token the token
* @return the username by token
*/
@Override
public String getUsernameByToken(String token) {
return null;
}
/**
* Verify permission error code.
*
* @param token the token
* @return the error code
*/
@Override
public ErrorCode verifyPermission(String token) {
return null;
}
/** /**
* Create user token string. * Create user token string.
* *
@ -261,6 +299,114 @@ public class UserAccountManagerImpl implements UserAccountManager {
return Hex.encodeHexString(cipherBytes); return Hex.encodeHexString(cipherBytes);
} }
/**
* Lock user account.
*
* @param username the username
*/
@Override
public void lockUserAccount(String username) {
userAccountMapper.lockUserAccount(username);
}
/**
* Unlock user account.
*
* @param username the username
*/
@Override
public void unlockUserAccount(String username) {
userAccountMapper.unlockUserAccount(username);
}
/**
* Upgrade login time.
*
* @param username the username
*/
@Override
public void upgradeLoginTime(String username) {
userAccountMapper.upgradeLoginTime(username);
}
/**
* Create user account user account.
*
* @param username the username
* @param password the password
* @param operators the operators
* @return the user account
*/
@Override
public UserAccount createUserAccount(String username, String password, String operators) {
return userAccountMapper.addUserAccount(username, password, operators);
}
/**
* Delete user account.
*
* @param username the username
* @param operators the operators
*/
@Override
public void deleteUserAccount(String username, String operators) {
userAccountMapper.delUserAccount(username, operators);
}
/**
* Disable user account.
*
* @param username the username
* @param operators the operators
*/
@Override
public void disableUserAccount(String username, String operators) {
userAccountMapper.disableUserAccount(username, operators);
}
/**
* Verify token permission error code.
*
* @param token the token
* @return the error code
*/
@Override
public ErrorCode verifyTokenPermission(String token) {
UserAccount user;
if (String.valueOf(false).equals(userPermissionConfigure.getAdminCheck())) {
return ErrorCode.ERR_OK;
}
if (userAccountCache.containsKey(token)) {
user = userAccountCache.get(token);
} else {
user = userAccountMapper.getUserByToken(token);
}
if (user == null) {
return ErrorCode.ERR_LOGOUT;
}
if (ADMIN_USERS.length == 0) {
ADMIN_USERS = userPermissionConfigure.getAdminUsers().split(disposeConfigure.getSplitChar());
}
UserAccount finalUser = user;
if (Arrays.stream(ADMIN_USERS).anyMatch(v -> v.equals(finalUser.getUsername()))) {
return ErrorCode.ERR_OK;
}
return ErrorCode.ERR_PERMISSION;
}
/**
* Token timeout boolean.
*
* @param lastAccess the last access
* @return the boolean
*/
private boolean tokenTimeout(String lastAccess) { private boolean tokenTimeout(String lastAccess) {
try { try {
return (System.currentTimeMillis() - Helper.getTimestampMilliSecond(lastAccess)) return (System.currentTimeMillis() - Helper.getTimestampMilliSecond(lastAccess))

View File

@ -13,6 +13,37 @@ import tk.mybatis.mapper.common.MySqlMapper;
*/ */
public interface UserAccountMapper extends Mapper<UserAccount>, public interface UserAccountMapper extends Mapper<UserAccount>,
IdsMapper<UserAccount>, MySqlMapper<UserAccount> { IdsMapper<UserAccount>, MySqlMapper<UserAccount> {
/**
* Add user account user account.
*
* @param username the username
* @param password the password
* @param operators the operators
* @return the user account
*/
UserAccount addUserAccount(@Param("username") String username,
@Param("password") String password,
@Param("operators") String operators);
/**
* Del user account.
*
* @param username the username
* @param operators the operators
*/
void delUserAccount(@Param("username") String username,
@Param("operators") String operators);
/**
* Disable user account.
*
* @param username the username
* @param operators the operators
*/
void disableUserAccount(@Param("username") String username,
@Param("operators") String operators);
/** /**
* Gets user by name. * Gets user by name.
* *

View File

@ -51,6 +51,16 @@ public class UserAccount implements Serializable {
*/ */
private String password; private String password;
/**
* The Create time.
*/
private String createTime;
/**
* The Operators.
*/
private String operators;
/** /**
* The Last login time. * The Last login time.
*/ */
@ -78,10 +88,6 @@ public class UserAccount implements Serializable {
/** /**
* The Status. * The Status.
* 0: 正常
* 1: 锁定
* 2: 禁用
* 3: 删除
*/ */
private Integer status; private Integer status;
} }

View File

@ -22,6 +22,51 @@ public interface UserAccountService {
*/ */
MulReturnType<ErrorCode, String> loginService(String username, String password) throws NoSuchAlgorithmException; MulReturnType<ErrorCode, String> loginService(String username, String password) throws NoSuchAlgorithmException;
/**
* Create user account mul return type.
*
* @param username the username
* @param password the password
* @param token the token
* @return the mul return type
*/
MulReturnType<ErrorCode, UserAccount> createUserAccount(String username, String password, String token);
/**
* Lock user account error code.
*
* @param username the username
* @return the error code
*/
ErrorCode lockUserAccount(String username);
/**
* Unlock user account error code.
*
* @param username the username
* @return the error code
*/
ErrorCode unlockUserAccount(String username);
/**
* Delete user account error code.
*
* @param username the username
* @param token the token
* @return the error code
*/
ErrorCode deleteUserAccount(String username, String token);
/**
* Disable user account error code.
*
* @param username the username
* @param token the token
* @return the error code
*/
ErrorCode disableUserAccount(String username, String token);
/** /**
* Logout service error code. * Logout service error code.
* *

View File

@ -2,9 +2,9 @@ package com.dispose.service.impl;
import com.dispose.common.ConstValue; import com.dispose.common.ConstValue;
import com.dispose.common.ErrorCode; import com.dispose.common.ErrorCode;
import com.dispose.common.UserAccountStatus;
import com.dispose.config.DisposeConfigure; import com.dispose.config.DisposeConfigure;
import com.dispose.manager.UserAccountManager; import com.dispose.manager.UserAccountManager;
import com.dispose.mapper.UserAccountMapper;
import com.dispose.pojo.entity.UserAccount; import com.dispose.pojo.entity.UserAccount;
import com.dispose.pojo.po.MulReturnType; import com.dispose.pojo.po.MulReturnType;
import com.dispose.service.UserAccountService; import com.dispose.service.UserAccountService;
@ -23,12 +23,15 @@ import java.security.NoSuchAlgorithmException;
@Slf4j @Slf4j
public class UserAccountServiceImpl implements UserAccountService { public class UserAccountServiceImpl implements UserAccountService {
/**
* The User account manager.
*/
@Resource @Resource
private UserAccountManager userAccountManager; private UserAccountManager userAccountManager;
@Resource /**
private UserAccountMapper userAccountMapper; * The Dispose configure.
*/
@Resource @Resource
private DisposeConfigure disposeConfigure; private DisposeConfigure disposeConfigure;
@ -49,17 +52,17 @@ public class UserAccountServiceImpl implements UserAccountService {
} }
/** /**
* Login service m return type. * Login service mul return type.
* *
* @param username the username * @param username the username
* @param password the password * @param password the password
* @return the m return type * @return the mul return type
* @throws NoSuchAlgorithmException the no such algorithm exception * @throws NoSuchAlgorithmException the no such algorithm exception
*/ */
@Override @Override
public MulReturnType<ErrorCode, String> loginService(String username, String password) throws NoSuchAlgorithmException { public MulReturnType<ErrorCode, String> loginService(String username, String password) throws NoSuchAlgorithmException {
userAccountMapper.upgradeLoginTime(username); userAccountManager.upgradeLoginTime(username);
UserAccount loginUser = userAccountMapper.getUserByName(username); UserAccount loginUser = userAccountManager.getUserByName(username);
// 该用户是否存在 // 该用户是否存在
if (loginUser == null) { if (loginUser == null) {
@ -68,7 +71,7 @@ public class UserAccountServiceImpl implements UserAccountService {
} }
// 用户是否被锁定 // 用户是否被锁定
if (loginUser.getStatus() == ConstValue.UserAccountStatus.LOCKED) { if (loginUser.getStatus() == UserAccountStatus.LOCKED.getCode()) {
log.error("User {} is locked", username); log.error("User {} is locked", username);
return MulReturnType.<ErrorCode, String>builder().firstParam(ErrorCode.ERR_USERLOCK).build(); return MulReturnType.<ErrorCode, String>builder().firstParam(ErrorCode.ERR_USERLOCK).build();
} }
@ -88,7 +91,7 @@ public class UserAccountServiceImpl implements UserAccountService {
return MulReturnType.<ErrorCode, String>builder().firstParam(ErrorCode.ERR_PASSWORDMORE).build(); return MulReturnType.<ErrorCode, String>builder().firstParam(ErrorCode.ERR_PASSWORDMORE).build();
} else if (errTimes >= ConstValue.GlobalConfigure.ALLOW_PWD_ERR_TIMES) { } else if (errTimes >= ConstValue.GlobalConfigure.ALLOW_PWD_ERR_TIMES) {
// 锁定账户 // 锁定账户
userAccountMapper.lockUserAccount(username); userAccountManager.lockUserAccount(username);
log.error("User {} is locked", username); log.error("User {} is locked", username);
return MulReturnType.<ErrorCode, String>builder().firstParam(ErrorCode.ERR_USERLOCK).build(); return MulReturnType.<ErrorCode, String>builder().firstParam(ErrorCode.ERR_USERLOCK).build();
} else { } else {
@ -98,8 +101,8 @@ public class UserAccountServiceImpl implements UserAccountService {
} }
return MulReturnType.<ErrorCode, String>builder() return MulReturnType.<ErrorCode, String>builder()
.firstParam(userAccountManager.getUserToken(username).getFirstParam()) .firstParam(ErrorCode.ERR_OK)
.secondParam(userAccountManager.getUserToken(username).getSecondParam()).build(); .secondParam(userAccountManager.getUserToken(username)).build();
} }
/** /**
@ -111,7 +114,7 @@ public class UserAccountServiceImpl implements UserAccountService {
*/ */
@Override @Override
public ErrorCode logoutService(String username, String token) { public ErrorCode logoutService(String username, String token) {
UserAccount loginUser = userAccountMapper.getUserByName(username); UserAccount loginUser = userAccountManager.getUserByName(username);
if (loginUser == null) { if (loginUser == null) {
log.error("User {} not exists", username); log.error("User {} not exists", username);
@ -119,11 +122,9 @@ public class UserAccountServiceImpl implements UserAccountService {
} }
// 注销 // 注销
ErrorCode err = userAccountManager.verifyUserLogin(username, token);
userAccountManager.cleanUserToken(username); userAccountManager.cleanUserToken(username);
return err; return ErrorCode.ERR_OK;
} }
/** /**
@ -134,13 +135,143 @@ public class UserAccountServiceImpl implements UserAccountService {
*/ */
@Override @Override
public UserAccount getUserByToken(String token) { public UserAccount getUserByToken(String token) {
String username = userAccountManager.getUsernameByToken(token); return userAccountManager.getUserByToken(token);
if (username != null && username.length() > 0) {
return userAccountMapper.getUserByName(username);
} }
log.error("according to token [{}] not found username", token); /**
return null; * Create user account mul return type.
*
* @param username the username
* @param password the password
* @param token the token
* @return the mul return type
*/
@Override
public MulReturnType<ErrorCode, UserAccount> createUserAccount(String username, String password, String token) {
UserAccount user = userAccountManager.getUserByName(username);
UserAccount optUser = userAccountManager.getUserByToken(token);
if (optUser == null) {
return MulReturnType.<ErrorCode, UserAccount>builder()
.firstParam(ErrorCode.ERR_PERMISSION).build();
}
if (user != null) {
return MulReturnType.<ErrorCode, UserAccount>builder()
.firstParam(ErrorCode.ERR_USEREXIST)
.secondParam(user).build();
}
ErrorCode err = userAccountManager.verifyTokenPermission(token);
if (err != ErrorCode.ERR_OK) {
return MulReturnType.<ErrorCode, UserAccount>builder()
.firstParam(err).build();
}
return MulReturnType.<ErrorCode, UserAccount>builder()
.firstParam(ErrorCode.ERR_OK)
.secondParam(userAccountManager.createUserAccount(username, password, optUser.getUsername()))
.build();
}
/**
* Lock user account error code.
*
* @param username the username
* @return the error code
*/
@Override
public ErrorCode lockUserAccount(String username) {
UserAccount user = userAccountManager.getUserByName(username);
if (user == null) {
return ErrorCode.ERR_USERNOTFOUND;
}
userAccountManager.lockUserAccount(username);
return ErrorCode.ERR_OK;
}
/**
* Unlock user account error code.
*
* @param username the username
* @return the error code
*/
@Override
public ErrorCode unlockUserAccount(String username) {
UserAccount user = userAccountManager.getUserByName(username);
if (user == null) {
return ErrorCode.ERR_USERNOTFOUND;
}
userAccountManager.unlockUserAccount(username);
return ErrorCode.ERR_OK;
}
/**
* Delete user account error code.
*
* @param username the username
* @param token the token
* @return the error code
*/
@Override
public ErrorCode deleteUserAccount(String username, String token) {
UserAccount user = userAccountManager.getUserByName(username);
if (user == null) {
return ErrorCode.ERR_USERNOTFOUND;
}
UserAccount optUser = userAccountManager.getUserByToken(token);
if (optUser == null) {
return ErrorCode.ERR_PERMISSION;
}
ErrorCode err = userAccountManager.verifyTokenPermission(token);
if (err != ErrorCode.ERR_OK) {
return err;
}
userAccountManager.deleteUserAccount(username, optUser.getUsername());
return ErrorCode.ERR_OK;
}
/**
* Disable user account error code.
*
* @param username the username
* @param token the token
* @return the error code
*/
@Override
public ErrorCode disableUserAccount(String username, String token) {
UserAccount user = userAccountManager.getUserByName(username);
if (user == null) {
return ErrorCode.ERR_USERNOTFOUND;
}
UserAccount optUser = userAccountManager.getUserByToken(token);
if (optUser == null) {
return ErrorCode.ERR_PERMISSION;
}
ErrorCode err = userAccountManager.verifyTokenPermission(token);
if (err != ErrorCode.ERR_OK) {
return err;
}
userAccountManager.disableUserAccount(username, optUser.getUsername());
return ErrorCode.ERR_OK;
} }
} }

View File

@ -2,10 +2,25 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dispose.mapper.UserAccountMapper"> <mapper namespace="com.dispose.mapper.UserAccountMapper">
<!-- mapper xml文件中只编写复杂逻辑的SQL SQL单独拿出来写与代码解耦SQL的熟练编写是每个研发必备的技能 --> <!-- mapper xml文件中只编写复杂逻辑的SQL SQL单独拿出来写与代码解耦SQL的熟练编写是每个研发必备的技能 -->
<select id="addUserAccount" resultType="com.dispose.pojo.entity.UserAccount">
INSERT INTO user_account(username, password, operators, status)
SELECT #{username}, #{password}, #{operators}, ${@com.dispose.common.UserAccountStatus@NORMAL.getCode()}
FROM DUAL
WHERE NOT EXISTS(
SELECT username
FROM user_account
where username = #{username, jdbcType=VARCHAR}
);
SELECT *
FROM user_account
WHERE username = #{username, jdbcType=VARCHAR}
</select>
<select id="getUserByName" resultType="com.dispose.pojo.entity.UserAccount"> <select id="getUserByName" resultType="com.dispose.pojo.entity.UserAccount">
SELECT * SELECT *
FROM user_account FROM user_account
WHERE username = #{username} WHERE username = #{username, jdbcType=VARCHAR}
</select> </select>
<select id="getUserByToken" resultType="com.dispose.pojo.entity.UserAccount"> <select id="getUserByToken" resultType="com.dispose.pojo.entity.UserAccount">
@ -23,7 +38,7 @@
SELECT lastAccess SELECT lastAccess
FROM user_account FROM user_account
WHERE username = #{username} WHERE username = #{username, jdbcType=VARCHAR}
</select> </select>
<select id="upgradeLoginTime" resultType="java.lang.String"> <select id="upgradeLoginTime" resultType="java.lang.String">
@ -34,7 +49,7 @@
SELECT lastLoginTime SELECT lastLoginTime
FROM user_account FROM user_account
WHERE username = #{username} WHERE username = #{username, jdbcType=VARCHAR}
</select> </select>
<select id="upgradeToken" resultType="java.lang.String"> <select id="upgradeToken" resultType="java.lang.String">
@ -45,7 +60,7 @@
SELECT token SELECT token
FROM user_account FROM user_account
WHERE username = #{username} WHERE username = #{username, jdbcType=VARCHAR}
</select> </select>
<select id="setPwdErrTimes" resultType="java.lang.Integer"> <select id="setPwdErrTimes" resultType="java.lang.Integer">
@ -56,13 +71,31 @@
SELECT pwdErrTimes SELECT pwdErrTimes
FROM user_account FROM user_account
WHERE username = #{username} WHERE username = #{username, jdbcType=VARCHAR}
</select> </select>
<update id="delUserAccount">
UPDATE
user_account
SET status = ${@com.dispose.common.UserAccountStatus@DELETED.getCode()},
operators = #{operators},
lockTime = CURRENT_TIMESTAMP
WHERE username = #{username, jdbcType=VARCHAR}
</update>
<update id="disableUserAccount">
UPDATE
user_account
SET status = ${@com.dispose.common.UserAccountStatus@DISABLED.getCode()},
operators = #{operators},
lockTime = CURRENT_TIMESTAMP
WHERE username = #{username, jdbcType=VARCHAR}
</update>
<update id="lockUserAccount"> <update id="lockUserAccount">
UPDATE UPDATE
user_account user_account
SET status = 1, SET status = ${@com.dispose.common.UserAccountStatus@LOCKED.getCode()},
lockTime = CURRENT_TIMESTAMP lockTime = CURRENT_TIMESTAMP
WHERE username = #{username, jdbcType=VARCHAR} WHERE username = #{username, jdbcType=VARCHAR}
</update> </update>
@ -70,7 +103,7 @@
<update id="unlockUserAccount"> <update id="unlockUserAccount">
UPDATE UPDATE
user_account user_account
SET status = 0, SET status = ${@com.dispose.common.UserAccountStatus@NORMAL.getCode()},
lockTime = 0 lockTime = 0
WHERE username = #{username, jdbcType=VARCHAR} WHERE username = #{username, jdbcType=VARCHAR}
</update> </update>

View File

@ -0,0 +1,67 @@
package com.dispose.test.Global;
import com.dispose.common.ErrorCode;
import com.dispose.pojo.po.MulReturnType;
import com.dispose.service.UserAccountService;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.springframework.test.context.ActiveProfiles;
import javax.annotation.Resource;
/**
* The type Init test environment.
*/
@Slf4j
@Getter
@ActiveProfiles("local")
public class InitTestEnvironment {
/**
* The connect timeout.
*/
public static final int HTTP_CONNECT_TIMEOUT = 10000;
/**
* The constant logToken.
*/
private static String logToken = "45509b805d955cfd5ef7093e27a8bb99b3733d9a7bf90e88ba528bcbd29c6122";
/**
* The User name.
*/
private final String USER_NAME = "admin";
/**
* The Password.
*/
private final String PASSWORD = "c3855e6b6bb120450f160ba91134522868f89d36062f2061ebeefd80817e1d58";
/**
* The User account service.
*/
@Resource
private UserAccountService userAccountService;
/**
* Init virtual device.
*/
@BeforeClass
public static void initVirtualDevice() {
log.warn("Current Used Virtual Dispose Device");
}
/**
* User login.
*
* @throws Exception the exception
*/
@Before
public void userLogin() throws Exception {
MulReturnType<ErrorCode, String> ret = userAccountService.loginService(getUSER_NAME(), getPASSWORD());
Assert.assertEquals(ret.getFirstParam(), ErrorCode.ERR_OK);
logToken = ret.getSecondParam();
Assert.assertNotNull(logToken);
Assert.assertNotEquals(logToken.length(), 0);
}
}

View File

@ -0,0 +1,203 @@
package com.dispose.test.manager;
import com.dispose.common.ErrorCode;
import com.dispose.common.UserAccountStatus;
import com.dispose.manager.UserAccountManager;
import com.dispose.mapper.UserAccountMapper;
import com.dispose.pojo.entity.UserAccount;
import com.dispose.test.Global.InitTestEnvironment;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.security.NoSuchAlgorithmException;
/**
* The type User account manager test.
*/
@RunWith(SpringRunner.class)
@Slf4j
@SpringBootTest
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Transactional
@Rollback
public class UserAccountManagerTest extends InitTestEnvironment {
/**
* The User account cache manager.
*/
@Resource
private UserAccountManager userAccountManager;
@Resource
private UserAccountMapper userAccountMapper;
@Resource
private ObjectMapper objectMapper;
@Override
public void userLogin() {
}
@Test
public void a1_getUserByName() {
userAccountMapper.selectAll().forEach(v -> {
try {
String token = userAccountManager.getUserToken(v.getUsername());
Assert.assertNotNull(token);
Assert.assertNotEquals(0, token.length());
UserAccount user = userAccountManager.getUserByToken(token);
Assert.assertEquals(user.getUsername(), v.getUsername());
log.info(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user));
} catch (NoSuchAlgorithmException | JsonProcessingException e) {
log.error(e.getMessage());
Assert.fail();
}
});
}
@Test
public void a2_getUserByToken() {
userAccountMapper.selectAll().forEach(v -> {
UserAccount user = userAccountManager.getUserByName(v.getUsername());
Assert.assertEquals(user.getUsername(), v.getUsername());
Assert.assertEquals(user.getPassword(), v.getPassword());
Assert.assertEquals(user.getStatus(), v.getStatus());
try {
log.info(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user));
} catch (JsonProcessingException e) {
e.printStackTrace();
Assert.fail();
}
});
}
@Test
public void a3_getUserToken() {
userAccountMapper.selectAll().forEach(v -> {
try {
String userToken = userAccountManager.getUserToken(v.getUsername());
String userToken2 = userAccountManager.getUserToken(v.getUsername());
Assert.assertEquals(userToken, userToken2);
log.info("{} token : [{}]", v.getUsername(), userToken);
} catch (NoSuchAlgorithmException e) {
log.error(e.getMessage());
Assert.fail();
}
});
}
@Test
public void a4_setUserPwdErrTimes() {
userAccountMapper.selectAll().forEach(v -> {
for (int i = 0; i < 3; i++) {
userAccountManager.setUserPwdErrTimes(v.getUsername(), i);
UserAccount user = userAccountMapper.getUserByName(v.getUsername());
int times = userAccountManager.getUsrPwdErrTimes(v.getUsername());
Assert.assertNotNull(user);
Assert.assertEquals(i, (long) user.getPwdErrTimes());
Assert.assertEquals(i, times);
try {
log.info(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user));
} catch (JsonProcessingException e) {
e.printStackTrace();
Assert.fail();
}
}
});
}
@Test
public void a5_cleanUserToken() {
userAccountMapper.selectAll().forEach(v -> {
try {
String userToken = userAccountManager.getUserToken(v.getUsername());
UserAccount user = userAccountMapper.getUserByName(v.getUsername());
Assert.assertNotNull(userToken);
Assert.assertEquals(user.getToken(), userToken);
userAccountManager.cleanUserToken(v.getUsername());
Assert.assertEquals(ErrorCode.ERR_LOGOUT, userAccountManager.verifyToken(userToken));
log.info(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(v));
} catch (JsonProcessingException | NoSuchAlgorithmException e) {
e.printStackTrace();
Assert.fail();
}
});
}
@Test
public void a6_verifyTokenTest() throws NoSuchAlgorithmException {
String userToken = userAccountManager.getUserToken(getUSER_NAME());
String userToken2 = userAccountManager.getUserToken(getUSER_NAME());
Assert.assertEquals(userToken, userToken2);
Assert.assertEquals(userAccountManager.verifyToken(userToken), ErrorCode.ERR_OK);
Assert.assertEquals(userAccountManager.verifyToken(userToken + "123"), ErrorCode.ERR_LOGOUT);
}
@Test
public void a7_userAccountStatus() {
userAccountMapper.selectAll().forEach(v -> {
userAccountManager.lockUserAccount(v.getUsername());
UserAccount user = userAccountMapper.getUserByName(v.getUsername());
Assert.assertNotNull(user);
Assert.assertEquals((long) user.getStatus(), UserAccountStatus.LOCKED.getCode());
userAccountManager.unlockUserAccount(v.getUsername());
user = userAccountMapper.getUserByName(v.getUsername());
Assert.assertNotNull(user);
Assert.assertEquals((long) user.getStatus(), UserAccountStatus.NORMAL.getCode());
userAccountManager.disableUserAccount(v.getUsername(), "admin");
user = userAccountMapper.getUserByName(v.getUsername());
Assert.assertNotNull(user);
Assert.assertEquals((long) user.getStatus(), UserAccountStatus.DISABLED.getCode());
userAccountManager.deleteUserAccount(v.getUsername(), "admin");
user = userAccountMapper.getUserByName(v.getUsername());
Assert.assertNotNull(user);
Assert.assertEquals((long) user.getStatus(), UserAccountStatus.DELETED.getCode());
});
}
@Test
public void a8_verifyTokePermission() {
userAccountMapper.selectAll().forEach(v -> {
try {
String token = userAccountManager.getUserToken(v.getUsername());
Assert.assertNotNull(token);
Assert.assertEquals(ErrorCode.ERR_OK, userAccountManager.verifyTokenPermission(token));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
Assert.fail();
}
});
}
}

View File

@ -1,7 +1,7 @@
package com.dispose.test.mapper; package com.dispose.test.mapper;
import com.dispose.common.ConstValue;
import com.dispose.common.Helper; import com.dispose.common.Helper;
import com.dispose.common.UserAccountStatus;
import com.dispose.mapper.UserAccountMapper; import com.dispose.mapper.UserAccountMapper;
import com.dispose.pojo.entity.UserAccount; import com.dispose.pojo.entity.UserAccount;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
@ -70,12 +70,12 @@ public class UserAccountMapperTest {
userAccountMapper.lockUserAccount("admin"); userAccountMapper.lockUserAccount("admin");
UserAccount user = userAccountMapper.getUserByName("admin"); UserAccount user = userAccountMapper.getUserByName("admin");
Assert.assertEquals(new Long(user.getStatus()), new Long(ConstValue.UserAccountStatus.LOCKED)); Assert.assertEquals(new Long(user.getStatus()), new Long(UserAccountStatus.LOCKED.getCode()));
log.info(objMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user)); log.info(objMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user));
userAccountMapper.unlockUserAccount("admin"); userAccountMapper.unlockUserAccount("admin");
user = userAccountMapper.getUserByName("admin"); user = userAccountMapper.getUserByName("admin");
Assert.assertEquals(new Long(user.getStatus()), new Long(ConstValue.UserAccountStatus.NORMAL)); Assert.assertEquals(new Long(user.getStatus()), new Long(UserAccountStatus.NORMAL.getCode()));
log.info(objMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user)); log.info(objMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user));
} }
@ -123,4 +123,43 @@ public class UserAccountMapperTest {
Assert.assertTrue(Helper.getTimestampDiffNow(dt) < 2); Assert.assertTrue(Helper.getTimestampDiffNow(dt) < 2);
} }
@Test
public void a6_addUserAccess() throws JsonProcessingException {
UserAccount add = userAccountMapper.addUserAccount("xajhuang2", "test123", "admin");
Assert.assertNotNull(add);
UserAccount user = userAccountMapper.getUserByName("xajhuang2");
Assert.assertNotNull(user);
log.info(objMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user));
log.info(objMapper.writerWithDefaultPrettyPrinter().writeValueAsString(add));
add = userAccountMapper.addUserAccount("xajhuang", "test123", "admin");
Assert.assertNotNull(add);
}
@Test
public void a7_delUserAccount() throws JsonProcessingException {
String username = "xajhuang2";
UserAccount add = userAccountMapper.addUserAccount(username, "test123", "admin");
Assert.assertNotNull(add);
log.info(objMapper.writerWithDefaultPrettyPrinter().writeValueAsString(add));
userAccountMapper.delUserAccount(username, "admin");
UserAccount user = userAccountMapper.getUserByName(username);
Assert.assertNotNull(user);
Assert.assertEquals((long)user.getStatus(), UserAccountStatus.DELETED.getCode());
log.info(objMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user));
}
@Test
public void a8_disableUserAccount() throws JsonProcessingException {
String username = "xajhuang2";
UserAccount add = userAccountMapper.addUserAccount(username, "test123", "admin");
Assert.assertNotNull(add);
log.info(objMapper.writerWithDefaultPrettyPrinter().writeValueAsString(add));
userAccountMapper.disableUserAccount(username, "admin");
UserAccount user = userAccountMapper.getUserByName(username);
Assert.assertNotNull(user);
Assert.assertEquals((long)user.getStatus(), UserAccountStatus.DISABLED.getCode());
log.info(objMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user));
}
} }

View File

@ -0,0 +1,110 @@
package com.dispose.test.service;
import com.dispose.common.ErrorCode;
import com.dispose.pojo.entity.UserAccount;
import com.dispose.pojo.po.MulReturnType;
import com.dispose.service.UserAccountService;
import com.dispose.test.Global.InitTestEnvironment;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.security.NoSuchAlgorithmException;
/**
* The type User account service test.
*/
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Transactional
@Rollback
public class UserAccountServiceTest extends InitTestEnvironment {
/**
* The constant token.
*/
private static String token = "";
/**
* The User account service.
*/
@Resource
private UserAccountService userAccountService;
/**
* User login test.
*
* @throws NoSuchAlgorithmException the no such algorithm exception
*/
@Before
public void userLoginTest() throws NoSuchAlgorithmException {
MulReturnType<ErrorCode, String> ret = userAccountService.loginService(getUSER_NAME(),
getPASSWORD());
if (ret.getFirstParam() == ErrorCode.ERR_OK) {
UserAccountServiceTest.token = ret.getSecondParam();
}
}
/**
* T 1 log service test.
*
* @throws NoSuchAlgorithmException the no such algorithm exception
*/
@Test
public void t1_logServiceTest() throws NoSuchAlgorithmException {
MulReturnType<ErrorCode, String> ret = userAccountService.loginService(getUSER_NAME(),
getPASSWORD());
Assert.assertEquals(ret.getFirstParam(), ErrorCode.ERR_OK);
Assert.assertNotNull(ret.getSecondParam());
Assert.assertEquals(ret.getSecondParam(), UserAccountServiceTest.token);
ret = userAccountService.loginService(null, null);
Assert.assertEquals(ret.getFirstParam(), ErrorCode.ERR_USERNOTFOUND);
ret = userAccountService.loginService(getUSER_NAME(), "12345");
Assert.assertEquals(ret.getFirstParam(), ErrorCode.ERR_PASSWORD);
}
/**
* T 2 logout service test.
*/
@Test
public void t2_logoutServiceTest() {
ErrorCode err = userAccountService.logoutService(getUSER_NAME(), token);
Assert.assertEquals(err, ErrorCode.ERR_OK);
err = userAccountService.logoutService(getUSER_NAME(), token + "1235");
Assert.assertEquals(err, ErrorCode.ERR_LOGOUT);
}
/**
* T 3 get user by token test.
*/
@Test
public void t3_getUserByTokenTest() {
UserAccount username = userAccountService.getUserByToken(UserAccountServiceTest.token);
Assert.assertEquals(username.getUsername(), getUSER_NAME());
Assert.assertNull(userAccountService.getUserByToken(UserAccountServiceTest.token + "1235"));
}
/**
* T 4 auth token check test.
*/
@Test
public void t4_authTokenCheckTest() {
Assert.assertEquals(userAccountService.authTokenCheck(token), ErrorCode.ERR_OK);
Assert.assertEquals(userAccountService.authTokenCheck(token + "1235"), ErrorCode.ERR_LOGOUT);
}
}