基于Struts2 Action类条件弹窗打开JSP及跨系统二次认证问询
Got it, let's break down how to implement your dual-authentication popup flow in Struts2. The core idea is: let the Action handle the auth check, trigger a frontend popup if needed, handle the popup login via AJAX, and refresh the original page once the second auth is done.
1. 在SearchAction中实现双认证判断逻辑
First, we'll add logic in your SearchAction to check if the user has completed both system authentications. If not, we'll return a result that tells the frontend to show the login popup.
public class SearchAction extends ActionSupport { private boolean isDualAuthenticated; public String execute() { // 检查用户是否完成两个系统的认证 boolean firstSysAuth = checkFirstSystemAuthentication(); boolean secondSysAuth = checkSecondSystemAuthentication(); isDualAuthenticated = firstSysAuth && secondSysAuth; if (!isDualAuthenticated) { // 返回结果触发登录弹窗 return "showLoginPopup"; } // 已完成双认证,执行正常搜索逻辑 performSearchOperation(); return SUCCESS; } // 模拟检查第一个系统的认证状态(替换为实际API调用) private boolean checkFirstSystemAuthentication() { return (Boolean) ServletActionContext.getRequest().getSession() .getAttribute("firstSysAuthenticated"); } // 模拟检查第二个系统的认证状态 private boolean checkSecondSystemAuthentication() { return (Boolean) ServletActionContext.getRequest().getSession() .getAttribute("secondSysAuthenticated") != null; } // 你的正常搜索逻辑 private void performSearchOperation() { // 获取搜索结果,为JSP设置属性 } // 供前端获取认证状态的getter public boolean isDualAuthenticated() { return isDualAuthenticated; } }
2. 配置Struts.xml映射结果
Next, update your struts.xml to map the Action results. We'll add a result for showing the popup, and a separate Action to handle the popup login submission.
<struts> <package name="default" extends="struts-default"> <action name="search" class="com.yourpackage.SearchAction"> <!-- 正常搜索成功返回Search.jsp --> <result name="success">/Search.jsp</result> <!-- 返回Search.jsp并携带弹窗触发标记 --> <result name="showLoginPopup">/Search.jsp</result> </action> <!-- 处理弹窗登录请求的Action --> <action name="popupLogin" class="com.yourpackage.PopupLoginAction"> <result name="success" type="json"> <param name="root">loginResponse</param> </result> </action> </package> </struts>
3. 在Search.jsp中添加弹窗和前端逻辑
Now, modify Search.jsp to display the login popup when the Action indicates the user isn't fully authenticated. We'll use jQuery for AJAX handling and basic CSS for the popup styling.
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>Search Page</title> <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> <style> /* 弹窗遮罩层 */ .auth-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.6); display: none; justify-content: center; align-items: center; z-index: 1000; } /* 登录弹窗容器 */ .login-modal { background: #fff; padding: 2rem; border-radius: 8px; box-shadow: 0 0 15px rgba(0,0,0,0.2); width: 350px; } .form-group { margin-bottom: 1rem; } label { display: block; margin-bottom: 0.5rem; } input { width: 100%; padding: 0.5rem; border: 1px solid #ddd; border-radius: 4px; } .btn-group { display: flex; gap: 1rem; justify-content: flex-end; } button { padding: 0.5rem 1rem; border: none; border-radius: 4px; cursor: pointer; } .btn-submit { background: #007bff; color: white; } .btn-cancel { background: #6c757d; color: white; } </style> </head> <body> <!-- 正常搜索表单 --> <div class="search-container"> <h1>Search Resources</h1> <form action="search" method="post"> <input type="text" name="searchQuery" placeholder="Enter your query..." required> <button type="submit">Search</button> </form> <!-- 搜索结果展示区域 --> <div class="results"> <s:if test="searchResults != null"> <!-- 渲染搜索结果 --> </s:if> </div> </div> <!-- 双系统登录弹窗 --> <div class="auth-overlay" id="loginPopup"> <div class="login-modal"> <h3>Authenticate with Second System</h3> <form id="popupLoginForm"> <div class="form-group"> <label for="username">Username:</label> <input type="text" id="username" name="secondSysUsername" required> </div> <div class="form-group"> <label for="password">Password:</label> <input type="password" id="password" name="secondSysPassword" required> </div> <div class="btn-group"> <button type="submit" class="btn-submit">Login</button> <button type="button" class="btn-cancel" onclick="closePopup()">Cancel</button> </div> </form> </div> </div> <script> $(document).ready(function() { // 如果用户未完成双认证,显示弹窗 <s:if test="!isDualAuthenticated"> $('#loginPopup').css('display', 'flex'); </s:if> // 处理弹窗登录表单提交 $('#popupLoginForm').submit(function(e) { e.preventDefault(); $.ajax({ url: 'popupLogin', type: 'POST', data: $(this).serialize(), dataType: 'json', success: function(response) { if (response.success) { // 关闭弹窗并刷新页面,重新执行SearchAction $('#loginPopup').hide(); window.location.reload(); } else { alert('Login Failed: ' + response.message); } }, error: function() { alert('Something went wrong. Please try again later.'); } }); }); }); // 关闭弹窗函数 function closePopup() { $('#loginPopup').hide(); // 可选:根据需求跳转回上一页或清空表单 } </script> </body> </html>
4. 实现PopupLoginAction处理弹窗登录请求
Create a separate Action to handle the AJAX login request from the popup, validate the credentials against the second system, and update the session if successful.
public class PopupLoginAction extends ActionSupport { private String secondSysUsername; private String secondSysPassword; private LoginResponse loginResponse; public String execute() { loginResponse = new LoginResponse(); // 验证第二个系统的凭证(替换为实际API调用) boolean loginSuccess = validateSecondSystemCredentials(secondSysUsername, secondSysPassword); if (loginSuccess) { // 在Session中标记第二个系统认证成功 ServletActionContext.getRequest().getSession() .setAttribute("secondSysAuthenticated", true); loginResponse.setSuccess(true); loginResponse.setMessage("Authentication successful!"); } else { loginResponse.setSuccess(false); loginResponse.setMessage("Invalid username or password."); } return SUCCESS; } // 模拟第二个系统的凭证验证逻辑 private boolean validateSecondSystemCredentials(String username, String password) { return "validUser".equals(username) && "validPass123".equals(password); } // Getters and Setters public String getSecondSysUsername() { return secondSysUsername; } public void setSecondSysUsername(String secondSysUsername) { this.secondSysUsername = secondSysUsername; } public String getSecondSysPassword() { return secondSysPassword; } public void setSecondSysPassword(String secondSysPassword) { this.secondSysPassword = secondSysPassword; } public LoginResponse getLoginResponse() { return loginResponse; } public void setLoginResponse(LoginResponse loginResponse) { this.loginResponse = loginResponse; } // 封装登录响应的内部类 public static class LoginResponse { private boolean success; private String message; public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } }
关键注意事项
- 会话管理: 将双认证状态存储在用户Session中,避免每次调用Action都重复检查两个系统的认证状态,提升性能。
- 安全性: 始终使用HTTPS加密凭证传输,还可以添加验证码或限流机制防止暴力破解。
- 错误处理: 优化前端错误提示,使其更友好,同时为所有输入添加服务端验证。
- 弹窗体验: 可以在AJAX登录请求期间添加加载状态,让用户知道系统正在处理。
内容的提问来源于stack exchange,提问作者stackMan10

