单台web app 做登陆很简单,放到session里就可以。但稍微大的应用都是apache下挂着多台tomcat的,tomcat1的session 到tomcat2下就不管用了。tomcat间的session复制也比较费性能,我们尽量要保持web层的无状态。
上一篇apache_tomcat负载均衡配置完成后,我基于此业余做了基于struts的多台应用登陆/自动登陆处理,源码在附件中。
原理:
1、登陆后把信息用户名及密码加密放入cooekis(如果选择自动登陆),同时把User 对象放入session。下上文中通过session.getAttribute("User")来判断是否登陆
2、在访问时会有两个拦截器来处理
a.loginInterceptor
?? 从cookies中取得加密过的username和password,验证是否正确,将Uesr放入session
b.authInterceptor
?? 对需要登陆才能有的操作加入验证处理,如果没登陆将跳转到登陆页,登陆完成后跳转要操作的页面。
代码实现:
1、LoginInterceptor
/**
*
* 从cookies中恢复登陆
*
* @author 锅巴
* @version 1.0 2010-6-29
*/
public class LoginInterceptor implements Interceptor {??
???
??? public final static String CRYPTO_PWD = "865azo@44536_t";
??????
??? private UserDAO userDAO;
?
?
??? public String intercept(ActionInvocation arg0) throws Exception {
???????
???????
??????
??????? printCookies();
???????
??????? process(arg0);
????
??????? return arg0.invoke();
??? }
???
??? private void process(ActionInvocation arg0) throws Exception {
??????? Map session = arg0.getInvocationContext().getSession();
???????
??????? if(session != null && session.get(Statics.USER_SESSION_KEY) != null){
??????????? System.out.println("========== user is have in session ");
??????????? return ;
??????? }
???????????
???????
??????? HttpServletRequest request = ServletActionContext.getRequest();
??????? Cookie[] cookies = request.getCookies();
???????
??????? if(cookies == null)
??????????? return;
???????
???????
??????? for (Cookie cookie : cookies) {
??????????? if (Statics.COOKIE_REMEMBERME_KEY.equals(cookie.getName())
??????????????????? && !StringUtils.isEmpty(cookie.getValue())) {
??????????????? String[] split = cookie.getValue().split("-");
??????????????? String userName = DESCrypto.decrypt(split[0],CRYPTO_PWD);
??????????????? String password = DESCrypto.decrypt(split[1],CRYPTO_PWD);
??????????????? try {
??????????????????? User user = userDAO.attemptLogin(userName, password);
??????????????????? session.put(Statics.USER_SESSION_KEY, user);
??????????????? } catch (UserNotFoundException e) {
????????????????????
??????????????? }
??????????? }
??????? }
??? }??
???
???
??? private void printCookies(){
??????? System.out.println("========= printCookies statrt ========");
??????? Cookie[] cookies = ServletActionContext.getRequest().getCookies();
??????? if(cookies != null){
??????????? for(Cookie cook : cookies){
??????????????? System.out.println(cook.getName() + " : " + cook.getValue() + " : " + cook.getMaxAge() );
??????????? }
??????? }
??????
??????? System.out.println("========= printCookies end ========");
??? }
???
?
??????
???
??? public UserDAO getUserDAO() {
??????? return userDAO;
??? }
??? public void setUserDAO(UserDAO userDAO) {
??????? this.userDAO = userDAO;
??? }
??? public void destroy() {
??????? // TODO Auto-generated method stub
???????
??? }
??? public void init() {
??????? // TODO Auto-generated method stub
???????
??? }
}
2、AuthInterceptor
/**
* 必须验证要登陆的拦截器
* @author 锅巴
* @version 1.0 2010-6-29
*/
public class AuthInterceptor implements Interceptor{
??? private final static String ACTH_ERROR_TO_URL = "forwardLogin";
??
??? private static Log log = LogFactory.getLog(AuthInterceptor.class);
???
???
??? public void destroy() {
??????? // TODO Auto-generated method stub
???????
??? }
??? public void init() {
??????? // TODO Auto-generated method stub
???????
??? }
??? public String intercept(ActionInvocation arg0) throws Exception {
??????? // TODO Auto-generated method stub
?????? Map session = arg0.getInvocationContext().getSession();
?????? if(session == null || session.get(Statics.USER_SESSION_KEY) == null){
?????????? return getAuthErrorReturn(arg0);
?????? }
???????
?????? return arg0.invoke();
??? }
???
??? private String getAuthErrorReturn(ActionInvocation arg0){
?????
??????? HttpServletRequest request? =? ServletActionContext.getRequest();??
???????
??????
??????? String urlValue = request.getRequestURL().toString();
??????? if (request.getQueryString() != null)
??????????? urlValue += "?" + request.getQueryString();
??????? request.setAttribute(Statics.AUTH_LOGIN_GO, urlValue);
??????? log.debug("urlValue:" + urlValue);
??????? return ACTH_ERROR_TO_URL;
??? }
???
??
???
}
3、Login 登陆action
/**
*
* 描述
*
* @author 锅巴
* @version 1.0 2010-7-5
*/
public class LoginAction extends ActionSupport implements SessionAware,CookiesAware,ServletResponseAware,ServletRequestAware{
??? private Map session;
???
??? private Map cookie;
???
??? private HttpServletResponse response;
???
??? private UserDAO userDAO;
???
??? private String username;
???
??? private String password;
???
??? private String goUrl;
???
??? private HttpServletRequest request;
???
??? private boolean rememberMe;
???
???
???
??? public boolean isRememberMe() {
??????? return rememberMe;
??? }
??? public void setRememberMe(boolean rememberMe) {
??????? this.rememberMe = rememberMe;
??? }
??? @Override
??? public void setServletRequest(HttpServletRequest arg0) {
??????? // TODO Auto-generated method stub
??????? this.request = arg0;
??? }
??? public void setUserDAO(UserDAO userDAO) {
??????? this.userDAO = userDAO;
??? }
???
???
??? public String getGoUrl() {
??????? return goUrl;
??? }
??? public void setGoUrl(String goUrl) {
??????? this.goUrl = goUrl;
??? }
??? public String getUsername() {
??????? return username;
??? }
??? public void setUsername(String username) {
??????? this.username = username;
??? }
??? public String getPassword() {
??????? return password;
??? }
??? public void setPassword(String password) {
??????? this.password = password;
??? }
??? @Override
??? public void setServletResponse(HttpServletResponse arg0) {
??????? // TODO Auto-generated method stub
??????? this.response = arg0;
??? }
??? @Override
??? public void setSession(Map arg0) {
??????? // TODO Auto-generated method stub
??????? this.session = arg0;
??? }
??? @Override
??? public void setCookiesMap(Map arg0) {
??????? // TODO Auto-generated method stub
??????? this.cookie = arg0;
??? }
??? @Override
??? public String execute() throws Exception {
??????? // TODO Auto-generated method stub
??????? return SUCCESS;
??? }
???
???
???
??? public String postLogin() throws Exception {
??????? User user = null;
??????? try{
??????????? user = userDAO.attemptLogin(username, password);
??????? }catch(UserNotFoundException ex){
??????????? addActionError("登陆失败!");
??????????? return INPUT;
??????? }
???????
??????? processCookie(user);
???????
??????? return SUCCESS;
??? }
??? private void processCookie(User user) throws Exception {
??????? session.put(Statics.USER_SESSION_KEY, user);
???????
??????? //cookie value 不能有==这种情况,不能ie会拒绝该cookies
??????? Cookie cookie = new Cookie(Statics.COOKIE_REMEMBERME_KEY, DESCrypto.desCrypto(username.getBytes(), LoginInterceptor.CRYPTO_PWD)+ "-" + DESCrypto.desCrypto(password.getBytes(), LoginInterceptor.CRYPTO_PWD));
??????? if (rememberMe){
??????????? cookie.setMaxAge(60 * 60 * 24 * 14);
??????? }else{
??????????? cookie.setMaxAge(0);
??????? }
??????? cookie.setPath("/");
??????? cookie.setDomain("t.com");
??????? response.addCookie(cookie);
??? }
???
}
4、LoginOut 退出action
/**
*
* 描述
*
* @author 锅巴
* @version 1.0 2010-7-5
*/
public class LoginOutAction extends ActionSupport implements ServletResponseAware,ServletRequestAware{
??? private HttpServletResponse response;
???
??? private HttpServletRequest request;
???
???
??? @Override
??? public void setServletResponse(HttpServletResponse arg0) {
??????? // TODO Auto-generated method stub
??????? this.response=arg0;
??? }
???
???
??? @Override
??? public void setServletRequest(HttpServletRequest arg0) {
??????? // TODO Auto-generated method stub
??????? this.request = arg0;
??? }
??? @Override
??? public String execute() throws Exception {
??????? // TODO Auto-generated method stub
???????
???????
???????
??????? Cookie[] cookies = request.getCookies();??
??????? if (cookies!=null) {??
??????????? for (Cookie cookie : cookies) {??
??????????????? if (Statics.COOKIE_REMEMBERME_KEY.equals(cookie??
??????????????????????? .getName())) {
??????????????????? //清除cookie时要与增加时步骤一致 如path,domain
??????????????????? cookie.setPath("/");
??????????????????? cookie.setDomain("t.com");
??????????????????? cookie.setValue("");??
??????????????????? cookie.setMaxAge(0);??
??????????????????? response.addCookie(cookie);
??????????????? }??
??????????? }??
??????? }??
??????? HttpSession session = request.getSession(false);??
??????? if (session!=null)??
??????????? session.removeAttribute(Statics.USER_SESSION_KEY);??
???????
???
??????? System.out.println("============== login out ================");
??????? return SUCCESS;
??? }
???
}
5、struts.xml配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
??? "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
??? "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="default" namespace="/" extends="struts-default">
<interceptors>??
??????????? <interceptor name="loginInterceptor" class="com.my.interceptor.LoginInterceptor"></interceptor>
??????????? <interceptor name="authInterceptor" class="com.my.interceptor.AuthInterceptor"></interceptor>??
???????????
?????????
??????????? <!-- 默认拦截器堆栈 -->
??????????? <interceptor-stack name="loginDefaultStack">
??????????? <interceptor-ref name="loginInterceptor"></interceptor-ref>????
??????????????? <interceptor-ref name="authInterceptor"></interceptor-ref>??
??????????????? <interceptor-ref name="defaultStack"></interceptor-ref>??
??????????? </interceptor-stack>
???????????
??????????? <!-- 需要登陆验证的拦截器堆栈 -->
??????????? <interceptor-stack name="autowireDefault">
??????????? <interceptor-ref name="loginInterceptor"></interceptor-ref>
??????????????? <interceptor-ref name="defaultStack"></interceptor-ref>??
??????????? </interceptor-stack>
??????????????
??????? </interceptors>
???????
??????? <default-interceptor-ref name="autowireDefault"></default-interceptor-ref>
???????
??????? <global-results>
??????? <!-- 验证未通过跳转全局result -->??
??????????? <result name="forwardLogin" type="chain">
??????????? <param name="actionName">forwardLogin</param>
?????????? <param name="namespace">/common</param>
??? </result>??
??????? </global-results>
</package>
<include file="struts-conf/common.struts.xml"></include>
</struts>
6、common.struts.xml 配置
? <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
??? "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
??? "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="common" namespace="/common" extends="default">
<!--? 跳转登录 -->
<action name="forwardLogin" class="com.my.action.JumpLoginAction">
<result name="success" type="redirect">
/common/login.html?goUrl=${goUrl}
</result>
</action>
<!-- 登陆页面 -->
<action name="login" class="com.my.action.LoginAction">
<result name="success" type="dispatcher">
/common/login.jsp
</result>
</action>
<!-- 退出 -->
<action name="loginOut" class="com.my.action.LoginOutAction">
<result name="success" type="dispatcher">
/common/login_out.jsp
</result>
</action>
<!-- 登陆post操作 -->
<action name="postLogin" class="com.my.action.LoginAction" method="postLogin">
<result name="success" type="redirect">
${goUrl}
</result>
<result name="input" type="dispatcher">
/common/login.jsp
</result>
<interceptor-ref name="autowireDefault" />
<interceptor-ref name="validationWorkflowStack" />
</action>
<!-- 需要登陆验证的页面 -->
<action name="home" class="com.my.action.HomeAction">
<result name="success" type="dispatcher">
/index.jsp
</result>
<interceptor-ref name="loginDefaultStack" />
</action>
</package>
</struts>
注意事项:
1、LoginAction-postLogin-validation.xml ,可以按action 方法名来验证。
2、cookies 中不能含有"==",否则IE会写不进去。
3、写cookies与清cookies的操作要完全一致,否则清不了。
?? 如:??????????????
?? 写cookies
??? //cookie value 不能有==这种情况,不能ie会拒绝该cookies
??? Cookie cookie = new Cookie(Statics.COOKIE_REMEMBERME_KEY, DESCrypto.desCrypto(username.getBytes(), LoginInterceptor.CRYPTO_PWD)+ "-" + DESCrypto.desCrypto(password.getBytes(), LoginInterceptor.CRYPTO_PWD));
??????? if (rememberMe){
??????????? cookie.setMaxAge(60 * 60 * 24 * 14);
??????? }else{
??????????? cookie.setMaxAge(0);
??????? }
??????? cookie.setPath("/");
??????? cookie.setDomain("t.com");
??????? response.addCookie(cookie);
??? 清cookies
??????????????????? cookie.setPath("/");
??????????????????? cookie.setDomain("t.com");
??????????????????? cookie.setValue("");??
??????????????????? cookie.setMaxAge(0);??
??????????????????? response.addCookie(cookie);?
???
?