在jsp servlet中我们通常使用Servlet Filter控制用户是否登入, 是否有权限转到某个页面。在struts2中我们应该会想到他的拦截器(Interceptor), Interceptor在struts2中起着非常重要的作用。很多struts2中的功能都是使用Interceptor实现的。
需求:简单的登入界面,让用户输入用户名,密码,记住密码(remember me)。如果用户选中remember me的话,下次就不需要再登入了(使用cookie实现, 用需要点击logout取消remeber me功能)。如果用户起始输入的地址不是登入页面的话,在用户登入之后需要转到用户输入的起始地址。
功能概图:
项目文件概图:
struts.xml 配置部分:
<!-- 演示权限控制 -->
<package name="authority" extends="struts-default" namespace="/authority">
<interceptors>
<interceptor name="loginInterceptor" class="com.gq.action.LoginInterceptor"/>
<interceptor-stack name="loginDefaultStack">
<interceptor-ref name="loginInterceptor"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="loginDefaultStack"/>
<global-results>
<result name="login" type="redirect">/authority/login.jsp</result>
</global-results>
<action name="Index" class="com.gq.action.IndexAction">
<result>/authority/main.jsp</result>
<interceptor-ref name="loginDefaultStack"/>
</action>
<action name="Logout" class="com.gq.action.LogoutAction"></action>
<action name="Login" class="com.gq.action.LoginAction" method="login">
<result type="redirect">${goingToURL}</result>
<result name="input">/authority/login.jsp</result>
<interceptor-ref name="defaultStack"/>
</action>
<!-- 没有实现 class
<action name="Register" class="com.gq.action.LoginAction">
<result type="redirect">/authority/login.jsp</result>
<result name="input">/authority/register.jsp</result>
<interceptor-ref name="defaultStack"/>
</action>
-->
</package>
各文件描述和源代码:
IndexAction.java,直接跳转到 main.jsp,该action 名称为 “Index”,并配置有登陆权限验证拦截器!
public class IndexAction extends ActionSupport {
private static final long serialVersionUID = 7078603236740619967L;
@Override
public String execute() throws Exception {
// Just return to /main.jsp
return SUCCESS;
}
}
LoginAction.java,验证“登陆名”和“密码”是否正确,保存“用户”到 Session中,并根据参数决定是否保存Cookie
其中要判断:
1、用户直接进入 login.jsp的页面?验证成功后,跳转到 main.jsp页面。
2、用户从其他页面 xxx.jsp,因为没有权限验证失败而回到 login.jsp?则验证成功后,跳转到 xxx.jsp页面。
(这里为了演示简化,xxx.jsp 就指定为 main.jsp 页面)
public class LoginAction extends ActionSupport implements ServletResponseAware, SessionAware {
private static final long serialVersionUID = 2965422004870746408L;
private String loginName;
private String password;
private boolean rememberMe;
private HttpServletResponse response;
private Map session;
private String goingToURL;
public String getGoingToURL() {
return goingToURL;
}
public void setGoingToURL(String goingToURL) {
this.goingToURL = goingToURL;
}
public boolean isRememberMe() {
return rememberMe;
}
public void setRememberMe(boolean rememberMe) {
this.rememberMe = rememberMe;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public void setServletResponse(HttpServletResponse response) {
this.response = response;
}
public void setSession(Map session) {
this.session = session;
}
public String login() throws Exception {
System.out.println("In login..." + getLoginName());
try {
User user = new UserDAO().attemptLogin(getLoginName(), getPassword());
//Add cookie
if (rememberMe) {
response.addCookie(createCookie(user));
}
//Add into session
session.put(LoginInterceptor.USER_SESSION_KEY, user);
String goingToURL = (String) session.get(LoginInterceptor.GOING_TO_URL_KEY);
if (StringUtils.isNotBlank(goingToURL)){
setGoingToURL(goingToURL);
session.remove(LoginInterceptor.GOING_TO_URL_KEY);
} else {
setGoingToURL("Index.action");
}
return SUCCESS;
} catch (UserNotFoundException e) {
addActionMessage("user name or password is not corrected.");
return INPUT;
}
}
Cookie createCookie( User user ){
int SEVEN_DAYS = 60 * 60 * 24 * 7;
Cookie cookie = new Cookie(LoginInterceptor.COOKIE_REMEMBERME_KEY, createValue(user));
cookie.setMaxAge(SEVEN_DAYS);
return cookie;
}
String createValue( User user ){
return user.getLoginName()+ "==" + user.getPassword();
}
}
LoginInterceptor.java,登陆拦截器,根据 Session判断用户是否在线或根据Cookie解析能否登陆。
public class LoginInterceptor extends AbstractInterceptor {
private static final long serialVersionUID = -5889213773673649255L;
public static final String USER_SESSION_KEY = "wallet.session.user";
public static final String COOKIE_REMEMBERME_KEY = "wallet.cookie.rememberme";
public static final String GOING_TO_URL_KEY = "GOING_TO";
public static final String LOGIN = "login";
@Override
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("In LoginInterceptor...");
ActionContext actionContext = invocation.getInvocationContext();
HttpServletRequest request = (HttpServletRequest) actionContext.get(StrutsStatics.HTTP_REQUEST);
//用户在登录状态
Map<String,String> session = actionContext.getSession();
if (session != null && session.get(USER_SESSION_KEY) != null) {
System.out.println("In user is login, saved information in session...");
return invocation.invoke();
}
//用户从Cookie中解析信息,然后登录
return loginFromCookie(request, invocation, session);
}
String loginFromCookie(HttpServletRequest request, ActionInvocation invocation,Map session) throws Exception{
System.out.println("In loginFromCookie...");
Cookie[] cookies = request.getCookies();
if( cookies == null ){ //No cookies
setGoingToURL(session, invocation);
return LOGIN;
}
Cookie cookie = findCookieByName( cookies );
if( cookie == null ){ //No cookie by the name
setGoingToURL(session, invocation);
return LOGIN;
}
String loginName = parseLoginName( cookie );
String password = parsePassword( cookie );
if( loginName == null || password == null ){ //parse loginName or password fail...
setGoingToURL(session, invocation);
return LOGIN;
}
try {
User user = new UserDAO().attemptLogin(loginName, password);
session.put(USER_SESSION_KEY, user);
return invocation.invoke();
} catch (UserNotFoundException e) {
setGoingToURL(session, invocation);
return LOGIN;
}
}
Cookie findCookieByName(Cookie[] cookies) {
for( Cookie cookie : cookies ){
if(COOKIE_REMEMBERME_KEY.equals(cookie.getName())){
return cookie;
}
}
return null;
}
String parsePassword(Cookie cookie) {
String value = cookie.getValue();
if (StringUtils.isBlank(value)) {
return null;
}
String[] split = value.split("==");
if( split.length < 2 ){
return null;
}
return split[1];
}
String parseLoginName(Cookie cookie) {
String value = cookie.getValue();
if (StringUtils.isBlank(value)) {
return null;
}
String[] split = value.split("==");
return split[0];
}
private void setGoingToURL(Map session, ActionInvocation invocation) {
String url = "";
String namespace = invocation.getProxy().getNamespace();
if (StringUtils.isNotBlank(namespace) && !namespace.equals("/")) {
url = url + namespace;
}
String actionName = invocation.getProxy().getActionName();
if (StringUtils.isNotBlank(actionName)) {
url = url + "/" + actionName + ".action";
}
session.put(GOING_TO_URL_KEY, url);
}
}
LogoutAction.java,注销,清空Session中的信息,删除Cookie
public class LogoutAction extends ActionSupport implements ServletRequestAware,ServletResponseAware {
private static final long serialVersionUID = -7680746852412424580L;
private HttpServletRequest request;
private HttpServletResponse response;
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public void setServletResponse(HttpServletResponse response) {
this.response = response;
}
public String execute() throws Exception {
System.out.println("In logout..." + getNameForLogout());
removeFromSession();
removeFromCookies();
return "login";
}
void removeFromSession() {
HttpSession session = request.getSession(false);
if (session != null)
session.removeAttribute(LoginInterceptor.USER_SESSION_KEY);
}
void removeFromCookies() {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (LoginInterceptor.COOKIE_REMEMBERME_KEY.equals(cookie.getName())) {
cookie.setValue("");
cookie.setMaxAge(0);
response.addCookie(cookie);
return;
}
}
}
}
String getNameForLogout(){
HttpSession session = request.getSession(false);
if( session == null){
return "Session is null...";
}
User user = (User)session.getAttribute(LoginInterceptor.USER_SESSION_KEY);
return user.getLoginName();
}
}
User.java,一个简单的JavaBean
public class User {
// Used for login
private String loginName;
private String password;
// Information of user
private String name;
private String sex;
private int age;
//get/set 方法
@Override
public boolean equals(Object object) {
if(object==null || getClass()!=object.getClass()){
return false;
}
User user = (User)object;
return strEquals(getLoginName(), user.getLoginName()) &&
strEquals(getPassword(), user.getPassword()) &&
strEquals(getName(), user.getName()) &&
strEquals(getSex(), user.getSex()) &&
getAge() == user.getAge();
}
private boolean strEquals( String s1, String s2 ){
if( s1 == null ){
return false;
}
return s1.equals(s2);
}
@Override
public int hashCode() {
int result = 47;
result = 37*result + Integer.valueOf(age).hashCode();
result = 37*result + (loginName==null ? 0 : loginName.hashCode());
result = 37*result + (password==null ? 0 : password.hashCode());
result = 37*result + (name==null ? 0 : name.hashCode());
result = 37*result + (sex==null ? 0 : sex.hashCode());
return result;
}
}
UserDAO.java,一个简单的模拟的dao
public class UserDAO {
private static Map<String, User> users = new HashMap<String, User>();
public UserDAO(){
mockUsers();
}
public User attemptLogin(String loginName, String password) throws UserNotFoundException{
User user;
if( (user=findUser(loginName)) == null ){
throw new UserNotFoundException("Invalid User!");
}
if( !validPassword(password, user) ){
throw new UserNotFoundException("Invalid Password!");
}
return user;
}
User findUser( String loginName ){
return users.get(loginName);
}
boolean validPassword( String password, User user ){
return password.equals(user.getPassword());
}
private void mockUsers(){
User zhangsan = new User();
zhangsan.setLoginName("zhangsan@qq.com");
zhangsan.setPassword("zhangsan123");
zhangsan.setName("zhangsan");
zhangsan.setAge(22);
zhangsan.setSex("man");
User lisi = new User();
lisi.setLoginName("lisi@qq.com");
lisi.setPassword("lisi123");
lisi.setName("lisi");
lisi.setAge(25);
lisi.setSex("woman");
User wangwu = new User();
wangwu.setLoginName("wangwu@qq.com");
wangwu.setPassword("wangwu123");
wangwu.setName("wangwu");
wangwu.setAge(27);
wangwu.setSex("man");
users.put(zhangsan.getLoginName(), zhangsan);
users.put(lisi.getLoginName(), lisi);
users.put(wangwu.getLoginName(), wangwu);
}
}
UserNotFoundException.java,之定义封装的一个 Exception
public class UserNotFoundException extends Exception{
private static final long serialVersionUID = -5207325846250567308L;
public UserNotFoundException( String message ){
super( message );
}
}
login.jsp,登陆页面
<%@ page language="java" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>Login</title>
</head>
<body>
<h2>Login</h2>
<s:actionmessage/>
<s:actionerror/>
<s:form action="/authority/Login.action" method="post" validate="false" theme="xhtml">
<s:textfield name="loginName" label="Username"></s:textfield><br/>
<s:password name="password" label="Password"></s:password><br/>
<s:checkbox label="Remember Me" name="rememberMe"></s:checkbox>
<s:submit value="%{'Login'}"></s:submit>
</s:form>
<a href="/test_struct2/authority/register.jsp">Register</a>
</body>
</html>
main.jsp主页面
<%@ page language="java" pageEncoding="ISO-8859-1"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'main.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
This is Main page. <br>
<a href="/test_struct2/authority/Logout.action">Logout</a>
</body>
</html>
register.jsp ,未实现。。。