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>