Servlet与Filter两种方式实现身份验证和访问控制
创始人
2025-06-01 09:48:18
0

Servlet的session授权方式



Hello Welcome!

Username:
Password:
<%= request.getAttribute("message")%>
@WebServlet("/login")
public class RedirectController extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//转发req.getRequestDispatcher("index.jsp").forward(req,resp);//重定向//resp.sendRedirect("/servlet2");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);}
}
@WebServlet("/index")
public class IdefyController extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String name = req.getParameter("user");String password = req.getParameter("password");if (name.equals("xiaoxu") && password.equals("xiaoxu")){resp.getWriter().write("login successful!");}else {req.setAttribute("message","user or pass incorrect");req.getRequestDispatcher("index.jsp").forward(req,resp);}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);}
}

在这里插入图片描述
在这里插入图片描述
表单模拟的验证登录面临的新问题是这个验证登录只对index资源有效,不走验证流程,查看其他资源也可以访问,这显然是不对的。那么如何实现权限的控制呢?

会话技术session

  • 创建会话
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String name = req.getParameter("user");String password = req.getParameter("password");if (name.equals("xiaoxu") && password.equals("xiaoxu")){//session会话HttpSession session = req.getSession();session.setAttribute("isLogin","true");PrintWriter writer = resp.getWriter();writer.write("login successful!");writer.write("");}else {req.setAttribute("message","user or pass incorrect");req.getRequestDispatcher("index.jsp").forward(req,resp);}
}
//session会话
HttpSession session = req.getSession();
session.setAttribute("isLogin","true");

通过请求参数在HtppSession对象的实例中添加参数,该对象的实例是全局的,服务器状态的会话技术,通过添加表示来记录登录的状态。

  • 使用会话
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {if(req.getSession().getAttribute("isLogin") == null){resp.getWriter().write("Not currently logged in!");}else {if (req.getSession().getAttribute("isLogin").equals("true")){req.setCharacterEncoding("utf-8");PrintWriter out=resp.getWriter();out.write("Test");}else {resp.getWriter().write("Not currently logged in!");}}

req.getSession().getAttribute("isLogin")方法获取创建会话是存入会话的表示,确认登录状态。

当前并未登录

在这里插入图片描述

直接访问资源

在这里插入图片描述

登录成功后

在这里插入图片描述
直接在url上访问资源

在这里插入图片描述
如上所示可以实现权限的管理,但缺点是每个资源都需要对session的判断,比较繁琐:

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {if(req.getSession().getAttribute("isLogin") == null){resp.getWriter().write("Not currently logged in!");}else {if (req.getSession().getAttribute("isLogin").equals("true")){req.setCharacterEncoding("utf-8");PrintWriter out=resp.getWriter();out.write("Test");}else {resp.getWriter().write("Not currently logged in!");}}
}
  • 消除会话

消除用户鉴权的核心就是销毁会话存储的标识:

//消除session会话
HttpSession session = request.getSession();
session.removeAttribute("isLogin");

Filter的授权方式

更多内容请移步Java开发网站的核心servlet

public class LoginFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {//super.init(filterConfig);}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {//请求和响应参数强转HttpServletRequest res = (HttpServletRequest) servletRequest;HttpServletResponse resp = (HttpServletResponse) servletResponse;if(res.getSession().getAttribute("isLogin") == null){resp.getWriter().write("Not currently logged in!");}else {if (res.getSession().getAttribute("isLogin").equals("true")){filterChain.doFilter(servletRequest,servletResponse);}else {resp.getWriter().write("Not currently logged in!");}}}@Overridepublic void destroy() {//super.destroy();}
}

这里将ServletRequest强转为HttpServletRequest

//请求和响应参数强转
HttpServletRequest res = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;

在这里插入图片描述

ServletRequest只是一个接口,实现了HttpServletRequest大多数方法,可以直接强转。

在web.xml配置fileter,也可以通过@WebFilter注解:

  webFiltercom.example.controller.LoginFilterwebFilter/*

web.xml的配置是由加载顺序的,因此注意配置的顺序,利用顺序配置过滤器链,过滤器配置在servlet之前。/*表示所有路径。Filter的执行顺序与在web.xml配置文件中的配置顺序一致,一般把Filter配置在所有的Servlet之前。

配置后再启动服务器直接将主页也权限控制了:

在这里插入图片描述
这里的解决方案是放开登录的主页即利用filter排除过滤不需要的页面:

webFiltercom.example.controller.LoginFilterwebFilter/*

过滤器中捕获相应需要释放的url:

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {//请求和响应参数强转HttpServletRequest res = (HttpServletRequest) servletRequest;HttpServletResponse resp = (HttpServletResponse) servletResponse;if (res.getServletPath().equals("/login") || res.getServletPath().equals("/index")){filterChain.doFilter(servletRequest,servletResponse);}else {if (res.getSession().getAttribute("isLogin") == null){resp.getWriter().write("Not currently logged in!");}if (res.getSession().getAttribute("isLogin").equals("true")){filterChain.doFilter(servletRequest,servletResponse);}}}

分别释放/login和/index的原因是前者是返回的登陆页面,后者是登陆权限判断的逻辑处理。(逻辑处理不释放,会导致登录不上系统)

通过HttpServletRequest对象的实例的getServletPath()方法获取请求的uri,对特定的url直接释放资源例如:/login。注意需要带/

对特定uri释放资源后,只有特定的uri会被放行其他都会被拦截:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

这里需要注意的是释放url的逻辑,看下图Filter的处理逻辑,既可以每个filter实现对servlet的过滤,也可以通过url的配置实现对整个servlet的控制:

在这里插入图片描述

案例的的filter的uri配置的是/*对所有的url拦截,需要释放登录和逻辑判断。Filter在拦截时,会对请求时拦截和请求后处理,这涉及到Filter的生命周期,只要释放了相应的uri其后的逻辑既可以正常执行,无论是页面还是处理逻辑。

Filter登录权限控制总结:

  1. 实现Filter类,并重新写方法
public class LoginFilter implements Filter {//重写方法
}
  1. 用户身份登录逻辑
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {//请求和响应参数强转HttpServletRequest res = (HttpServletRequest) servletRequest;HttpServletResponse resp = (HttpServletResponse) servletResponse;//需要释放的资源if (res.getServletPath().equals("/login") || res.getServletPath().equals("/index")){filterChain.doFilter(servletRequest,servletResponse);}else {//状态判断if (res.getSession().getAttribute("isLogin") == null){resp.getWriter().write("Not currently logged in!");}if (res.getSession().getAttribute("isLogin").equals("true")){filterChain.doFilter(servletRequest,servletResponse);}}
}

请求和响应参数必须要强转,因为ServletRequest只是一个接口,没有实现具体方法;对登录页面和逻辑的资源放行;非登录逻辑相关必须验证登录状态使用会话技术。

  1. 登录逻辑与会话技术

继承HttpServlet并实现相关方法,在方法体内编写验证和会话逻辑。

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String name = req.getParameter("user");String password = req.getParameter("password");if (name.equals("xiaoxu") && password.equals("xiaoxu")){//session会话HttpSession session = req.getSession();session.setAttribute("isLogin","true");PrintWriter writer = resp.getWriter();writer.write("login successful!");}else {req.setAttribute("message","user or pass incorrect");req.getRequestDispatcher("/login").forward(req,resp);}
}

不论通过ajxa还是form表单,这里都是查数据库验证角色是否存在,存在就设置会话标识,不存在返回登录页面并返回错误信息。

servlet实现身份登录.zip

相关内容

热门资讯

保存时出现了1个错误,导致这篇... 当保存文章时出现错误时,可以通过以下步骤解决问题:查看错误信息:查看错误提示信息可以帮助我们了解具体...
汇川伺服电机位置控制模式参数配... 1. 基本控制参数设置 1)设置位置控制模式   2)绝对值位置线性模...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
表格中数据未显示 当表格中的数据未显示时,可能是由于以下几个原因导致的:HTML代码问题:检查表格的HTML代码是否正...
本地主机上的图像未显示 问题描述:在本地主机上显示图像时,图像未能正常显示。解决方法:以下是一些可能的解决方法,具体取决于问...
表格列调整大小出现问题 问题描述:表格列调整大小出现问题,无法正常调整列宽。解决方法:检查表格的布局方式是否正确。确保表格使...
不一致的条件格式 要解决不一致的条件格式问题,可以按照以下步骤进行:确定条件格式的规则:首先,需要明确条件格式的规则是...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...