Struts2框架(七)

拦截器的应用

一般网站为了防止有人恶意登录(未登录就直接访问后台页面),都会用拦截器Interceptor来限制登录。

下边是一个拦截器登录限制和下载文件限制的一个例子,帮助理解和应用拦截器。

操作步骤如下:

第一步:创建一个登录页面login.html.代码如下。

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>Insert title here</title>

<link rel="stylesheet" type="text/css" href="js/themes/default/easyui.css">

<link rel="stylesheet" type="text/css" href="js/themes/icon.css">

 

<script type="text/javascript" src="js/jquery.min.js"></script>

<script type="text/javascript" src="js/jquery.easyui.min.js"></script>

<script type="text/javascript" src="js/easyui-lang-zh_CN.js"></script>

 

<script type="text/javascript">

$(function(){

//在这里编写jquery easyui的代码

$('#ff').dialog({    

    title: '登录界面',    

    width: 300,    

    height: 160,    

    closed: false,    

    cache: false,    

    modal: true,

    buttons:[{

text:'登录',

handler:function(){

$('#ff').form('submit', {    

    url:"login", 

    onSubmit: function(){    

        if($("#name").val()=="")  {

         $.messager.alert('提示','用户名不能为空'); 

         return false;

        }  

        if($("#pass").val()=="")  {

         $.messager.alert('提示','用户密码不能为空'); 

         return false;

        }  

    },  

    success:function(data){  

     var data=eval("("+data+")");//把后台Action传送过来的json字符串”[{"mess":"登录成功","url":"http://localhost:8080/struts2Pro/download"}]“转换成json格式数据。

        if(data[0]["mess"]==="登录成功"){//登录成功则关闭登录对话框,并跳转到前一个页面

         $('#ff').dialog("close"); 

         if(data[0]["url"]!=""){

         window.location.href=data[0]["url"];//跳转到原来页面

         }else{

                                                                window.location.href="index.html";//跳转主页面

                                                        }         

        }else{

         alert(data[0]["mess"]);

         $("#name").focus();

        }

    }    

});      

}

},{

text:'关闭',

handler:function(){

$('#ff').dialog("close");    

}

}]

});    

});

 

</script>

</head>

<body>

<form id="ff" method="post">

<table>

<tr>

<td>用户名:</td>

<td><input type="text" id="name" name="name" />

</tr>

<tr>

<td>密码:</td>

<td><input type="password" id="pass" name="pass" />

</tr>

</table>

</form>

</body>

</html>

运行结果如下图所示。

 

 

第二步:创建接收登录表单的参数Action,LoginAction.java代码如下。

package action;

import java.io.IOException;

import java.io.UnsupportedEncodingException;

 

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ModelDriven;

import bussiness.Blogin;

import entity.LoginEntity;

 

public class LoginAction implements ModelDriven {

private HttpServletResponse response;// 用于获取servlet中的请求对象。便于向客户反馈信息

private HttpServletRequest request;// 用于获取servlet中的请求对象。便于获取表单传送过来的各种数据,如删除或更新时传送过来的关键字id的值

private HttpSession session;//声明用户的会话,它用于记录用户的状态

private LoginEntity loginEntity=new LoginEntity();//在这里必须进行实例化

public LoginEntity getLoginEntity() {

return loginEntity;

}

public void setLoginEntity(LoginEntity loginEntity) {

this.loginEntity = loginEntity;

}

@Override

public Object getModel() {

// TODO Auto-generated method stub

return loginEntity;

}

public LoginAction(){

response=ServletActionContext.getResponse();//获取Response对象

request=ServletActionContext.getRequest();//获取Request对象

session=request.getSession();//创建用户会话,该对象是用于记录用户的状态

try {

request.setCharacterEncoding("utf-8");//设置接数据的编码为utf-8

response.setContentType("text/html;charset=utf-8");//设置输出编码为utf-8,以防出现乱码

} catch (UnsupportedEncodingException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

public String execute() throws IOException{

//检测登录用户和密码是否是合法的用户,若是则把用户的信息保存起来

if(Blogin.checkUser(loginEntity.getName(), loginEntity.getPass())){

session.setAttribute("user", loginEntity);//把用户的信息保存起来

if(session.getAttribute("redirect")!=null){//判断是否是从其它页面跳转过来,若是则登录成功后返回原来的页面

response.getWriter().println("[{\"mess\":\"登录成功\",\"url\":\""+session.getAttribute("redirect")+"\"}]");

 

}else{

//登录成功但不是从其它的页面跳转过来的

response.getWriter().println("[{\"mess\":\"登录成功\",\"url\":\"\"}]");

}

}else{

//登录失败

response.getWriter().println("[{\"mess\":\"登录失败\",\"url\":\"\"}]");

}

return null;

}

}

struts.xml代码如下。

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE struts PUBLIC

"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"

"http://struts.apache.org/dtds/struts-2.3.dtd">

 

<struts>

<constant name="struts.enable.DynamicMethodInvocation" value="true" />

<constant name="struts.devMode" value="true" />

<package name="default" namespace="/" extends="struts-default">

<action name="login" class="action.LoginAction">

</action>

</package>

</struts>

 

第三步:创建一个下载的页面(详细创建过程请看4.7节),download.html代码如下:

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>Insert title here</title>

</head>

<body>

 <a href="download?fileName=aa.jpg">下载一张图片</a><br>

</body>

</html>

 

第四步:创建处理请求下载文件的Action(详细创建过程请看4.7节),DownloadAction.java代码如下:

package action;

import java.io.*;

import javax.servlet.http.*;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class DownloadAction extends ActionSupport {

private String fileName;//获取客户请求下载的fileName要一样,且对它进行封装

 

public String getFileName() {

return fileName;

}

public void setFileName(String fileName) {

this.fileName = fileName;

}

@Override

public String execute() throws Exception {

return "success";

}

public String input() throws Exception{

        return INPUT;

    }

public InputStream getInputStream() throws IOException {

//获取request对象,以便进行接收用户的请求参数,即请下载的文件

HttpServletRequest request = ServletActionContext.getRequest();

//获取下载图片的真实物理路径

String path = request.getRealPath("/download");

//创建输入流用于读到要下载的文件。

InputStream is = new FileInputStream(new File(path, fileName));

return is;

}

}

 

 

struts.xml代码如下。

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE struts PUBLIC

"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"

"http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>

<constant name="struts.enable.DynamicMethodInvocation" value="true" />

<constant name="struts.devMode" value="true" />

<package name="default" namespace="/" extends="struts-default">

<action name="login" class="action.LoginAction">

</action>

<action name="download" class="action.DownloadAction">

<!--  <result name="input">/login.html</result> -->

<result type="stream">

<!-- inputName默认就是InputStream,可以省略,也可以自己修改,如改成aaa, 则Action里的方法也要改成public 

InputStream getAaa() -->

<param name="inputName">InputStream</param>

<param name="contentDisposition">attachment;fileName=${fileName}</param>

</result>

</action>

</package>

</struts>

第五步:在Java Resource/src目录下创建一个数据包,包名为interceptor

 

第六步:右击”interceptor“数据包,弹出的快捷菜单。

 

第七步:选择”new->class“创建一个拦截器,拦截器的名称为LoginInterceptor,并实现Interceptor接口 。

 

第八步:单击”Finish“,完成拦截器的创建。

 

为了拦截没有登录的用户进行系统,所以下面我们对它进行修改,完整代码如下。

package interceptor;

import javax.servlet.http.HttpSession;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionInvocation;

import com.opensymphony.xwork2.ActionSupport;

import com.opensymphony.xwork2.interceptor.Interceptor;

import action.LoginAction;

import bussiness.Blogin;

import entity.LoginEntity;

public class LoginInterceptor implements Interceptor {

private String INPUT;

@Override

public void destroy() {

System.out.println("拦截器销毁");

}

 

@Override

public void init() {

System.out.println("拦截器加载");

 

}

@Override

public String intercept(ActionInvocation arg0) throws Exception {

//获取内容对象,即会话对象session

HttpSession session=ServletActionContext.getRequest().getSession();

System.out.println("进入拦截器");

//如果是登录Action则不进行拦截

if(arg0.getAction() instanceof LoginAction){

return arg0.invoke();

}

//通过session获取登录用户的信息

LoginEntity loginEntity=(LoginEntity) session.getAttribute("user");

//若用户信息为null,说明用户没有登录,则返回到登录的页面,若存在则要检测用户是否是合法用户若是则允许进行下面内容,否则拦截不能进行下一面内容

if(loginEntity != null){

if(Blogin.checkUser(loginEntity.getName(), loginEntity.getPass())){

//如果用户已经登录,则把保存跳转页面的的会话属性设置为空

session.setAttribute("redirect",null);

return arg0.invoke();//允许进入下面的内容

}else{

//获取action

 ActionSupport action = (ActionSupport) arg0.getAction();

//把请求Action的页面地址保存到属性名为redirect中

 session.setAttribute("redirect",ServletActionContext.getRequest().getHeader("referer"));

 return action.LOGIN;//设置Action返回值。即返回到login.html页面。

}

}else{

//获取action

 ActionSupport action = (ActionSupport) arg0.getAction();

//把请求Action的页面地址保存到属性名为redirect中

 session.setAttribute("redirect",ServletActionContext.getRequest().getHeader("referer"));

 return action.LOGIN;//设置Action返回值。

}

}

}

 

 

 

struts.xml代码如下。

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE struts PUBLIC

"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"

"http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>

<constant name="struts.enable.DynamicMethodInvocation" value="true" />

<constant name="struts.devMode" value="true" />

<package name="default" namespace="/" extends="struts-default">

<interceptors>

<!-- 定义自己的拦截器 -->

<interceptor name="auth" class="interceptor.LoginInterceptor" />

<!--拦截器栈 -->

<interceptor-stack name="securityStack">

<!-- 系统默认拦截器栈  若没有在我们栏截器栈中指定默认栏截器它将不会被执行-->

<interceptor-ref name="defaultStack" />

<interceptor-ref name="auth" />

</interceptor-stack>

</interceptors>

<!-- 定义一个全局的返回类型 -->

<global-results>

         <result name="login">/login.html</result

 </global-results>

<action name="login" class="action.LoginAction">

</action>

 

<action name="download" class="action.DownloadAction">

<!--  <result name="input">/login.html</result> -->

<result type="stream">

<!-- inputName默认就是InputStream,可以省略,也可以自己修改,如改成aaa, 则Action里的方法也要改成public 

InputStream getAaa() -->

<param name="inputName">InputStream</param>

<param name="contentDisposition">attachment;fileName=${fileName}</param>

</result>

<!-- 在此Action中使用拦截器 -->  

  <interceptor-ref name="securityStack" />

</action>

</package>

</struts>