struts2中用interceptor实现权限控制

    在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 ,未实现。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值