class InvalidLoginException extends Exception {
}
就可以了,什么都不用干在你的login函数里: if( 判断条件满足 ) {
throw new InvalidLoginException();
}就行了
}
就可以了,什么都不用干在你的login函数里: if( 判断条件满足 ) {
throw new InvalidLoginException();
}就行了
public InvalidLoginException(String str){
super(str);
}
}
或者在里面定义一个消息代号来层层上抛也可以
public class InvalidLoginException extends Exception {
protected int msgNO;
public InvalidLoginException (int msgNO){
super();
this.msgNO=msgNO;
} public int getMsgNo(){
return this.msgNO;
}
}
比如说你的服务提供认证功能,就是你上面的哪个接口.那么可能n客户机都会到你哪里认证,而且是并发的.如果你不能区别每一个客户,那你如何做到按照每个客户计时?记录次数?
先找点关于SessionServer方面的资料看看.
这样简单的计数一般是不可行,比如在1分钟之内,A,B,C三个客户登录,都登录失败,这时计数就到达三次了,下面无法操作,而且也不符合逻辑.
super();
}
public ServiceLocatorException(String msg){
super(msg);
}
这也太简单了,我早会了,就是不懂得如何实现
““如果一定的时间内(1分钟)出现一定次数(3次)的登录错误,就锁定账户10分钟,并抛出一个异常””
┌──┐ ┌────┐ ┌───────┐
│用户│-用户令牌->│认证服务│--会话检查->│会话服务管理器│
└──┘ └────┘ └───────┘
你的真正的业务逻辑实际上不是“认证服务(接口)”提供的,这个接口实现在对用户的权限检查之前实际要请求“会话服务管理器”,对于每个不同用户的认证次数、认证许可时延等信息实际上都是在会话服务管理器中维护。
这里的SessionServer实际上是Name-Value对的数据维护每个用户的不同会话,简单的实现使用Map就可以了。关键在于需要为每个用户区别不同的“令牌”。
(1) 只是为了做示例,所以只处理了一些理想状况,没有处理异常的情况;
(2) 没有处理已经登录的成功用户再次登录的状态;
(3) 结构和算法并不是最好;
(4) 没有处理用户令牌,基于一个用户只在一个客户端登录的假设;
(5) 总之,还有很多缺陷. 但是目的就是为了演示.
做到了:如果一定的时间内(1分钟)出现一定次数(3次)的登录错误,就锁定账户10分钟,并抛出一个异常.[使用1分钟代替了10分钟].
源代码如下:
-----------------------------------------------------------------
public interface IAuthentication {
public boolean login (String userName, String userPassword) throws Exception;
}
-----------------------------------------------------------------
abstract class AuthenticationTemplate implements IAuthentication {
public boolean login (String userName, String userPassword) throws Exception {
if(userName==null||userPassword==null||userName.length()==0) {
throw new IllegalArgumentException("Invalid input");
}
SessionServer ss = SessionServer.getInstance(); // Check login permission
if(!ss.checkLoginPermission(userName)) {
throw new Exception("User loacked. Cannot login now.");
} // todo : login here
boolean loginResult = doRealLogin(userName, userPassword); // Update session server status
ss.updateLogin(userName, loginResult); return loginResult;
} protected abstract boolean doRealLogin(String userName, String password);
}
-----------------------------------------------------------------
class AuthenticationImpl extends AuthenticationTemplate {
protected boolean doRealLogin(String userName, String password) {
return userName.equals(password);
}
}
-----------------------------------------------------------------
class SessionServer {
private final Map map;
private SessionServer() {map=Collections.synchronizedMap(new HashMap());}
private static class SessionServerHolder {
static final SessionServer INSTANCE = new SessionServer();
}
static SessionServer getInstance() {return SessionServerHolder.INSTANCE;} boolean checkLoginPermission(String userName) throws Exception {
if (userName==null) {throw new IllegalArgumentException();}
synchronized(map) {
if ( !map.containsKey(userName) ) {
UserStatus status = new UserStatus();
status.setCreateTime(System.currentTimeMillis());
status.setUserName(userName);
status.setLoginStatus(UserStatus.STATUS_UNLOGIN);
status.setRetryTimes(0);
status.setLoginDelay(0L);
map.put(userName, status);
return true;
} else {
UserStatus status = (UserStatus)map.get(userName);
switch(status.getLoginStatus()) {
case UserStatus.STATUS_UNLOGIN:
return true;
case UserStatus.STATUS_LOGINING:
if(status.getRetryTimes()>=UserStatus.MAX_LOGIN_RETRY_TIMES) {
if ( System.currentTimeMillis()-status.getCreateTime() <= UserStatus.MAX_LOGIN_DELAY ) {
return false;
} else {
status = new UserStatus();
status.setCreateTime(System.currentTimeMillis());
status.setUserName(userName);
status.setLoginStatus(UserStatus.STATUS_UNLOGIN);
status.setRetryTimes(0);
status.setLoginDelay(0L);
map.put(userName, status);
return true;
}
} else return true;
case UserStatus.STATUS_LOGINED:
throw new Exception("Already logined.");
default:return false;
}
}
}
} void updateLogin(String userName, boolean loginResult) {
synchronized(map) {
if(!map.containsKey(userName)) return;
else {
UserStatus status = (UserStatus)map.get(userName);
if(loginResult) {
status.setLoginStatus(UserStatus.STATUS_LOGINED);
} else {
status.setLoginStatus(UserStatus.STATUS_LOGINING);
status.setRetryTimes(status.getRetryTimes()+1);
status.setLastModifyTime(System.currentTimeMillis());
}
}
}
}
}
-----------------------------------------------------------------
class UserStatus {
static final long MAX_LOGIN_DELAY = 60000;
static final int MAX_LOGIN_RETRY_TIMES = 3; static final int STATUS_UNLOGIN = 0;
static final int STATUS_LOGINING = 1;
static final int STATUS_LOGINED = 2; private long createTime;
private long lastModifyTime;
private String userName;
private int loginStatus;
private int retryTimes;
private long loginDelay; UserStatus() {} long getCreateTime() {return createTime;}
long getLastModifyTime() {return lastModifyTime;}
String getUserName() {return userName;}
int getLoginStatus() {return loginStatus;}
int getRetryTimes() {return retryTimes;}
long getLoginDelay() {return loginDelay;} void setCreateTime(long createTime) {this.createTime=createTime;}
void setLastModifyTime(long lastModifyTime) {this.lastModifyTime=lastModifyTime;}
void setUserName(String userName) {this.userName=userName;}
void setLoginStatus(int loginStatus) {this.loginStatus=loginStatus;}
void setRetryTimes(int retryTimes) {this.retryTimes=retryTimes;}
void setLoginDelay(long loginDelay) {this.loginDelay=loginDelay;} public boolean equals(Object o) {throw new UnsupportedOperationException();}
public int hashCode() {throw new UnsupportedOperationException();}
}
public class TestLogin extends TestCase {
public TestLogin(String name) {super(name);}
private IAuthentication auth = null;
protected void setUp() throws Exception {auth=new AuthenticationImpl();} public void testLoginSuccess() throws Exception {
boolean ret = auth.login("user1", "user1");
assertTrue(ret);
} public void testLoginLock() throws Exception {
// first login failure
boolean ret = auth.login("user2", "");
assertFalse(ret);
// Second login failure
ret = auth.login("user2", "");
assertFalse(ret);
// Third login failure
ret = auth.login("user2", "");
assertFalse(ret); // Now, user2 should be locked.
boolean exception = false;
try {
ret = auth.login("user2", "");
} catch(Exception ex) {
exception = true;
}
assertTrue(exception); // Sleep 60 seconds
try{Thread.sleep(60000);}catch(InterruptedException ex){} // now can login
ret = auth.login("user2", "");
assertFalse(ret);
ret = auth.login("user2", "user2");
assertTrue(ret);
}
}