如何隐藏/加密网页源代码?Struts1.X敏感数据屏蔽方案问询
Hey there! Let’s work through this sensitive data masking problem for your Struts 1.x app—totally get why you don’t want to disable right-click (that’s always a bad user experience move anyway). Here are practical, Struts-specific solutions to keep sensitive data out of your page source:
1. 后端核心处理(最可靠的方案)
Frontend tricks can always be bypassed, so fixing this at the backend (where data is rendered) is non-negotiable. Struts 1.x has two tailored approaches:
自定义Struts标签(精准控制)
This is my top recommendation because it lets you target exactly which fields need masking, avoiding accidental replacements of normal content. Here’s how to implement it:
- Write a custom tag class extending
TagSupportto handle masking logic:public class MaskTag extends TagSupport { private String value; // Raw sensitive value to mask private String type; // e.g., "ssn", "account" @Override public int doStartTag() throws JspException { String maskedValue = ""; if (value == null) { maskedValue = ""; } else switch (type) { case "ssn": if (value.length() == 9) { // Format SSN as ***-**-XXXX maskedValue = String.format("***-**-%s", value.substring(5)); } else { maskedValue = "Invalid SSN"; } break; case "account": if (value.length() >= 4) { // Show only last 4 digits maskedValue = String.format("****%s", value.substring(value.length() - 4)); } else { maskedValue = value; } break; default: maskedValue = value; } try { pageContext.getOut().write(maskedValue); } catch (IOException e) { throw new JspException("Failed to write masked value", e); } return SKIP_BODY; } // Getters and setters public String getValue() { return value; } public void setValue(String value) { this.value = value; } public String getType() { return type; } public void setType(String type) { this.type = type; } } - Register the tag in a TLD file (e.g.,
WEB-INF/custom.tld):<taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>custom</short-name> <tag> <name>mask</name> <tag-class>com.yourcompany.tags.MaskTag</tag-class> <body-content>empty</body-content> <attribute> <name>value</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>type</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> </taglib> - Use the tag in your JSPs to render sensitive fields:
<%@ taglib uri="/WEB-INF/custom.tld" prefix="custom" %> ... <tr> <td>SSN:</td> <td><custom:mask value="${user.ssn}" type="ssn"/></td> </tr> <tr> <td>Account Number:</td> <td><custom:mask value="${user.accountNumber}" type="account"/></td> </tr>
With this, the page source will only contain masked values—no raw sensitive data ever hits the client.
Servlet Global Filter (Batch Processing)
If you need to globally mask data matching specific patterns (like all SSNs), use a Servlet Filter to intercept and modify the response stream:
- Implement the Filter class with a response wrapper to capture output:
public class SensitiveDataFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse httpResponse = (HttpServletResponse) response; CharResponseWrapper responseWrapper = new CharResponseWrapper(httpResponse); chain.doFilter(request, responseWrapper); // Replace sensitive patterns in the response body String responseBody = responseWrapper.toString(); // Match SSNs (with or without hyphens) responseBody = responseBody.replaceAll("\\b\\d{3}-?\\d{2}-?\\d{4}\\b", "***-**-XXXX"); // Match 16-digit account numbers (show last 4 digits) responseBody = responseBody.replaceAll("\\b\\d{12}(\\d{4})\\b", "************$1"); httpResponse.getWriter().write(responseBody); } @Override public void init(FilterConfig filterConfig) throws ServletException {} @Override public void destroy() {} // Custom wrapper to capture response content private static class CharResponseWrapper extends HttpServletResponseWrapper { private final StringWriter writer = new StringWriter(); public CharResponseWrapper(HttpServletResponse response) { super(response); } @Override public PrintWriter getWriter() throws IOException { return new PrintWriter(writer); } @Override public String toString() { return writer.toString(); } } } - Register the filter in
web.xml:<filter> <filter-name>SensitiveDataFilter</filter-name> <filter-class>com.yourcompany.filters.SensitiveDataFilter</filter-class> </filter> <filter-mapping> <filter-name>SensitiveDataFilter</filter-name> <url-pattern>*.do</url-pattern> <!-- Intercept all Struts actions --> <url-pattern>*.jsp</url-pattern> <!-- Intercept direct JSP access --> </filter-mapping>
⚠️ Caution: Test your regex patterns carefully to avoid replacing valid business data (like order numbers that match account formats). This works best for highly standardized sensitive data.
2. Frontend Pitfalls to Avoid
- Never hide raw sensitive data with CSS and show masked values via JS—raw data will still be in the page source.
- Don’t store raw sensitive data in JS variables, hidden inputs, or
data-*attributes—these are all visible in source code. - For dynamic content, fetch pre-masked data from the backend instead of processing raw data client-side.
3. Validation Steps
After implementing, verify with these checks:
- Right-click the page and select View Page Source (don’t use the Elements tab in dev tools—JS can modify that, but source code is static).
- Search for raw sensitive values to confirm they’re not present.
- Test edge cases: empty values, malformed sensitive data, and ensure masking logic doesn’t break the UI.
内容的提问来源于stack exchange,提问作者user7491136

