攔截器的應用
一般網站爲了防止有人惡意登錄(未登錄就直接訪問後臺頁面),都會用攔截器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>