对于一个系统,我们要禁止用户在未登录的状态下就访问其他页面。而SSH中有两个解决方法,一是使用过滤器,二是使用拦截器。那我先来说说使用过滤器。
先来看下项目的构建
因为类挺多的,配置文件也有点多,在这里我主要贴出struts.xml、web.xml里的关于过滤器的配置信息,过滤器MyFilter.java以及login.jsp里的内容。
还有,因为是为了快速测试过滤器,所以用户信息我没有到数据库里查找,就自己在StudentAction.java
里设置了用户名和密码,再用equals()
判断的。
login.jsp页面
注意我这里的login.jsp
里使用form
表单提交信息的。
web.xml的配置
过滤jsp文件夹里的jsp页面
struts.xml里的配置
注意:type
一定要改成redirectAction
或者redirect
类型,不然有可能过滤器过滤不生效,因为result
默认为转发,转发的地址栏是不改变的,重定向的地址栏才发生改变!
MyFilter.java
package com.XXXXXX.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.*;
/**
* Servlet Filter implementation class MyFilter
*/
public class MyFilter implements Filter {
/**
* Default constructor.
*/
public MyFilter() {
// TODO Auto-generated constructor stub
}
/**
* @see Filter#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
}
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
/*定义过滤页面
* 过滤器一般在访问前起作用,拦截器可以任何时候
* */
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("========我是自定义过滤器=========");
HttpServletRequest request1=(HttpServletRequest) request;
HttpServletResponse response1=(HttpServletResponse) response;
HttpSession session=request1.getSession();
String url=request1.getServletPath();
String contextPath=request1.getContextPath();
if(url.equals(""))
url+="/";
if((url.startsWith("/")&&!url.startsWith("/jsp/login"))){//若访问后台资源 过滤到login
String name=(String)session.getAttribute("name");
String phone=(String)session.getAttribute("phone");
System.out.println("name: "+name);
if(name==null || phone==null){//转入管理员登陆页面
System.out.println(contextPath+"/jsp/login.jsp");
response1.sendRedirect(contextPath+"/jsp/login.jsp"); //重定向到登陆界面
return;
}
}
//继续回到原请求链
chain.doFilter(request, response);
}
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
}
}
运行结果:
1、不经过登录页面,直接访问../jsp/show.jsp
,发现show.jsp
被拦截,又跳转回login.jsp
2、不经过登录页面,再直接访问../stu/show.action
试试,发现又跳转回login.jsp
。因为访问show.action
就请求访问ShowAction.java
里的show()
方法,其返回值为“success”
,通过struts.xml
里的<result>
又再去访问show.jsp
。在访问show.jsp
过程中,show.jsp
先被过滤器过滤,判断用户是否登录,结果发现用户未登录,所以就不允许访问show.jsp
,返回到login.jsp页面。
3、登录后,再访问页面
请求登录页面
发现过滤器也进行了过滤,但不拦截(不判断用户是否登录)
输入登录信息:
前台运行结果
后台运行结果:
上面都是针对于表单提交,那用ajax提交用户信息,过滤器又该怎么写呢?
我这里的用户登录信息是从数据库里读取的,验证用户存在后,把数据存在Session中,向Ajax的success返回数据“success
”,不存在就返回"failure
",这里我只粘贴了管理员的登录验证。
首先看下前台页面部分代码:
<div class="name">
<label>用户名</label><input type="text" class="text" id="value_1" placeholder="用户名" name="account" tabindex="1">
</div>
<div class="pwd">
<label>密 码</label><input type="password" class="text" id="value_2" placeholder="密码" name="password" tabindex="2">
</div>
<input type="radio" id ="admin"name="role" checked=checked value="1">管理员
<input type="radio" id="user" name="role" value="2">用户</br>
<input type="button" class="submit" tabindex="3" value="登录" onclick="login()" >
<input type="button" class="regist" tabindex="4" value="注册" onclick="regist()">
注意我这里没有用form
表单提交数据,有时用form表单提交,再同时用ajax提交数据的话,会有冲突,看下我的按钮类型没有写成"submit"
.
相关Ajax代码:
function login(){
var account=$("#value_1").val();
var password = $("#value_2").val();
var role = $("input[name='role']:checked").val();
console.log(role);
/* var user = ${SessionScope.user}; */
if(account=="" || account==null ){
$('#value_1').focus;
alert("账号不能为空");
}
else if(password=="" || password==null){
$('#value_2').focus;
alert("密码不能为空");
}
else if(role=="1"){ //跳转到管理员
$.ajax({
type:'post',
url:"admin/login.action",
cache:false,
dadaType:"text",
data:{
"account":account,
"password":password,
},
success:function(result){
if(result!=null && result=="success"){
window.location.href="jsp/admin.jsp";
}
else if(result!=null && result=="failure"){
alert("用户不存在,请重新输入!");
$('#value_1').val("");
$('#value_2').val("");
$('#value_1').focus();
}
},
error : function(XMLHttpRequest, textStatus) {
var redirect = XMLHttpRequest.getResponseHeader("REDIRECT");
if(redirect=="REDIRECT"){
alert("请先登录");
window.location.href= XMLHttpRequest.getResponseHeader("CONTEXTPATH");
}
},
complete:function(XMLrequest, textStatus){
}
});
} /后面代码省略
过滤器的撰写:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("========我是自定义过滤器=========");
HttpServletRequest request1=(HttpServletRequest) request;
HttpServletResponse response1=(HttpServletResponse) response;
//如果是Ajax请求,则值为XMLHttpEequest
String type =request1.getHeader("X-Requested-With")==null ? "" : request1.getHeader("X-Requestesd-With");
String url=request1.getServletPath();
/* String contextPath =request1.getContextPath(); */
if(url.equals(""))
url+="/";
if((url.startsWith("/")&&!url.startsWith("/jsp/login"))){//若访问的不是登录界面,就开始判断
System.out.println("==========1=========");
if(request1.getSession().getAttribute("user")==null){ //判断用户是否处于登录状态
//说明未登录
if("XMLHttpRequest".equals(type)){
//处理Ajax请求,设置响应头信息
response1.setHeader("REDIRECT", "REDIRECT");
//需要跳转的页面
response1.setHeader("CONTEXTPATH", request1.getContextPath()+"/jsp/login.jsp");
}
else{
response1.sendRedirect(request1.getContextPath()+"/jsp/login.jsp");
}
}else{
//继续回到原请求链
chain.doFilter(request, response);
}
}
else{
//继续回到原请求链
chain.doFilter(request, response);
}
运行结果
1、未经登录直接访问admin.jsp
,访问失败,返回到login.jsp界面
2、登陆后访问成功
后台运行结果:
(测试数据都是随便写的,不要较真,不然截图要打码)
切记,退出时,要清除Session,或者设置Session时效。不然点击退出后,发现可以直接跳过登录访问后台界面。这是应为Session还存在。
如有不足之处,还请各位大佬给予纠正!