用Trigger实现的Logon/Logoff Audit

1. 创建存储Audit信息的表:


CREATE TABLE logonaudittable
(
  event       VARCHAR2(10),
  sid         NUMBER,
  serial#     NUMBER,
  timestamp   DATE,
  username    VARCHAR2(30),
  osuserid    VARCHAR2(30),
  machinename VARCHAR2(64)
)
/

2. 创建logon trigger:

CREATE OR REPLACE TRIGGER logonauditing AFTER LOGON ON database
DECLARE
  machinename VARCHAR2(64);
  osuserid    VARCHAR2(30);
  v_sid       NUMBER(10);
  v_serial    NUMBER(10);
 
  CURSOR c1 IS
    SELECT sid, serial#, osuser, machine
      FROM v$session WHERE audsid = userenv('sessionid');
BEGIN
  OPEN c1;
  FETCH c1 INTO v_sid, v_serial, osuserid, machinename;

  INSERT INTO logonaudittable VALUES ( 'LOGON', v_sid, v_serial, sysdate,
      user, osuserid, machinename );

  CLOSE c1;
END;
/

3. 创建LOGOFF Trigger:

CREATE OR REPLACE TRIGGER logoffauditing
BEFORE LOGOFF ON database
DECLARE
  machinename VARCHAR2(64);
  osuserid    VARCHAR2(30);
  v_sid       NUMBER(10);
  v_serial    NUMBER(10);
 
  CURSOR c1 IS
    SELECT sid, serial#, osuser, machine
      FROM v$session WHERE audsid = userenv('sessionid');
BEGIN
  OPEN c1;
  FETCH c1 INTO v_sid, v_serial, osuserid, machinename;

  INSERT INTO logonaudittable VALUES ( 'LOGOFF', v_sid, v_serial, sysdate,
    user, osuserid, machinename );

  CLOSE c1;
END;
/


查询结果:
~~~~~~

SQL> select event, sid, serial#, username, osuserid, to_char(timestamp,'dd-mon-yyyy hh24:mi:ss') as TIMESTAMP, machinename
from logonaudittable;

<think>根据用户需求,我们需要实现一个简单的登录验证机制,确保用户必须通过登录页面登录后才能访问特定页面(如/excelUpload)。由于HTML本身是无状态的,我们需要借助服务器端会话管理(如使用Session)或客户端令牌(如Token)来实现。这里我们采用常见的Session方案。 ### 实现思路: 1. 用户访问登录页面(/LogOn)进行登录。 2. 服务器验证用户凭证(如用户名密码),验证通过后在服务器创建会话(Session),并标记用户已登录。 3. 当用户尝试访问受保护的页面(如/excelUpload)时,服务器检查会话中是否存在登录标记,如果不存在则重定向到登录页面。 4. 用户注销时,销毁会话。 ### 具体步骤(以Java Web为例,使用Servlet和JSP): #### 1. 创建登录页面(login.jsp) ```html <!DOCTYPE html> <html> <head> <title>登录</title> </head> <body> <form action="login" method="post"> 用户名: <input type="text" name="username"><br> 密码: <input type="password" name="password"><br> <input type="submit" value="登录"> </form> </body> </html> ``` #### 2. 创建登录处理Servlet(LoginServlet.java) ```java @WebServlet("/login") public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String password = request.getParameter("password"); // 实际应用中应查询数据库验证 if("admin".equals(username) && "123456".equals(password)) { // 验证成功,创建会话并设置属性 HttpSession session = request.getSession(); session.setAttribute("user", username); // 重定向到受保护页面(或首页) response.sendRedirect("excelUpload"); } else { // 验证失败,返回登录页面 response.sendRedirect("LogOn?error=1"); } } } ``` #### 3. 创建受保护页面(excelUpload.jsp) 在访问该页面之前,我们需要检查用户是否登录。我们可以使用一个过滤器(Filter)来统一检查。 #### 4. 创建登录检查过滤器(AuthFilter.java) ```java @WebFilter("/LogOn/*") // 过滤/LogOn路径下的所有资源 public class AuthFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; HttpSession session = request.getSession(false); // 不创建新会话 // 检查是否是登录页面或登录请求,避免无限重定向 String path = request.getRequestURI().substring(request.getContextPath().length()); if (path.equals("/LogOn/login") || path.equals("/LogOn/")) { chain.doFilter(request, response); return; } // 检查session中是否有用户标识 if (session == null || session.getAttribute("user") == null) { // 未登录,重定向到登录页面 response.sendRedirect(request.getContextPath() + "/LogOn"); } else { chain.doFilter(request, response); } } } ``` #### 5. 配置过滤器 如果使用注解`@WebFilter`,则无需在web.xml配置。注意过滤的URL模式。 #### 6. 注销功能(LogoutServlet.java) ```java @WebServlet("/logout") public class LogoutServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(false); if (session != null) { session.invalidate(); // 销毁会话 } response.sendRedirect("LogOn"); // 重定向到登录页面 } } ``` ### 注意事项: 1. 上述示例中,登录页面URL为`http://localhost:8080/LogOn`,受保护页面在`/LogOn/excelUpload`,因此过滤器过滤`/LogOn/*`路径。 2. 在过滤器中,我们排除了登录页面和登录请求,否则会导致重定向循环。 3. 实际应用中,密码验证应使用安全的方式(如哈希加盐)存储和比较。 4. 会话管理需要注意安全性,防止会话固定攻击等。 ### 引用说明: 在实现登录验证时,我们使用了Session来跟踪用户登录状态,这是Web应用中常见的身份验证方式[^1]。同时,通过过滤器(Filter)对受保护资源进行统一检查,确保用户必须登录才能访问[^4]。 §§相关问题§§ 1. 如何防止登录表单被恶意提交? 2. 如何实现记住我(Remember Me)功能? 3. 如何防止会话劫持? 4. 在分布式环境中如何管理Session?</think>### 实现登录验证的解决方案 要实现用户必须通过登录页面验证后才能访问特定页面的功能,需要结合服务器端会话管理和访问控制机制。以下是具体实现步骤(以Java Web应用为例): #### 1. 创建登录页面(login.jsp) ```html <!-- http://localhost:8080/LogOn --> <form action="login" method="post"> 用户名:<input type="text" name="username"> 密码:<input type="password" name="password"> <button type="submit">登录</button> </form> ``` #### 2. 实现登录验证Servlet ```java @WebServlet("/login") public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) { String username = request.getParameter("username"); String password = request.getParameter("password"); // 验证用户凭证(实际应查询数据库) if (isValidUser(username, password)) { // 创建会话并设置认证标记 HttpSession session = request.getSession(); session.setAttribute("authenticated", true); response.sendRedirect("excelUpload"); } else { response.sendRedirect("LogOn?error=1"); } } private boolean isValidUser(String user, String pass) { // 实际实现应查询数据库[^3] return "admin".equals(user) && "securePass".equals(pass); } } ``` #### 3. 创建访问控制过滤器 ```java @WebFilter("/LogOn/*") public class AuthFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; HttpSession session = request.getSession(false); // 检查访问的是否为登录页面本身 boolean isLoginPage = request.getRequestURI().endsWith("/LogOn"); // 检查是否已认证 boolean isAuthenticated = (session != null && session.getAttribute("authenticated") != null); if (isLoginPage || isAuthenticated) { chain.doFilter(request, response); } else { // 未登录则重定向到登录页 response.sendRedirect(request.getContextPath() + "/LogOn"); } } } ``` #### 4. 配置受保护页面(excelUpload.jsp) ```jsp <%@ page contentType="text/html;charset=UTF-8" %> <!DOCTYPE html> <html> <head> <title>Excel上传</title> </head> <body> <h1>欢迎访问Excel上传页面</h1> <!-- 页面内容 --> </body> </html> ``` #### 5. 配置web.xml(可选) ```xml <filter> <filter-name>AuthFilter</filter-name> <filter-class>com.example.AuthFilter</filter-class> </filter> <filter-mapping> <filter-name>AuthFilter</filter-name> <url-pattern>/LogOn/*</url-pattern> </filter-mapping> ``` ### 关键实现原理 1. **会话管理**:使用`HttpSession`跟踪用户登录状态,设置`authenticated`属性作为认证标记[^1] 2. **访问控制**:通过过滤器拦截所有`/LogOn/*`路径的请求 3. **验证逻辑**: - 已登录用户:放行请求 - 未登录用户:重定向到登录页面 - 登录请求:直接处理认证逻辑 4. **安全增强**: ```java // 登录成功后使旧会话失效 request.getSession().invalidate(); HttpSession newSession = request.getSession(true); ``` ### 注意事项 1. **会话超时**:在`web.xml`中配置会话超时时间 ```xml <session-config> <session-timeout>30</session-timeout> <!-- 30分钟 --> </session-config> ``` 2. **安全传输**:生产环境应使用HTTPS加密传输 3. **密码安全**:密码存储应使用哈希算法(如BCrypt) 4. **重定向安全**:登录后重定向URL应验证是否属于当前域[^4] ### 引用说明 此方案基于会话的身份验证机制实现,参考了CAS系统的会话管理思想[^1]和SQL Server身份验证的会话控制机制[^4],通过服务器端会话状态跟踪用户认证状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值