You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vaadin 7.7.14中如何在v-uiId的RPC中隐藏密码

在Vaadin 7.7.14中避免PasswordField密码明文出现在RPC调用中

Vaadin 7.7.14的默认PasswordField会将输入的密码以明文形式通过RPC同步到服务端,要解决这个问题可以通过以下两种方案:

方案一:手动处理密码提交(无需修改Widgetset)

这种方式绕过Vaadin默认的字段值同步机制,通过自定义JavaScript调用在客户端加密密码后再传递到服务端,避免明文出现在RPC日志中。

  1. 初始化密码字段并设置唯一ID:
PasswordField senha = new PasswordField("Senha");
senha.setId("secure-password-field"); // 给字段设置ID,方便JS定位
  1. 创建提交按钮并绑定自定义处理逻辑:
Button submitBtn = new Button("提交");
submitBtn.addClickListener(e -> {
    // 执行JS获取密码并加密(示例用SHA-256,需依赖Web Crypto API)
    Page.getCurrent().getJavaScript().execute("" +
        "var rawPwd = document.getElementById('secure-password-field').value;" +
        "var encoder = new TextEncoder();" +
        "var data = encoder.encode(rawPwd);" +
        "crypto.subtle.digest('SHA-256', data).then(function(hash) {" +
        "   var hashedPwd = Array.from(new Uint8Array(hash))" +
        "       .map(b => b.toString(16).padStart(2, '0'))" +
        "       .join('');" +
        "   vaadin.post('" + UI.getCurrent().getUIId() + "', 'submit-encrypted-pwd', hashedPwd);" +
        "});"
    );
});
  1. 在服务端注册JavaScript回调,接收加密后的密码:
UI.getCurrent().addJavaScriptFunction("submit-encrypted-pwd", arguments -> {
    String encryptedPassword = arguments.getString(0);
    // 在这里处理加密后的密码(比如和服务端存储的哈希值比对)
    // 注意:客户端加密仅用于RPC传输防明文泄露,服务端仍需独立处理密码哈希存储
});

方案二:自定义PasswordField组件(需编译Widgetset)

通过扩展Vaadin的客户端GWT组件,修改密码同步时的RPC内容,替换明文为加密值。

  1. 服务端自定义字段类:
public class SecurePasswordField extends PasswordField {
    // 无需额外逻辑,仅作为客户端组件的服务端关联类
}
  1. 客户端GWT组件(重写文本同步逻辑):
package com.yourpackage.client;

import com.vaadin.client.ui.VPasswordField;
import com.vaadin.shared.ui.textfield.TextFieldServerRpc;
import elemental.util.Base64;

public class VSecurePasswordField extends VPasswordField {

    @Override
    protected void onValueChange() {
        super.onValueChange();
        // 替换明文为Base64加密值(实际建议用SHA-256等强哈希算法)
        String rawPwd = getValue();
        String encryptedPwd = Base64.encode(rawPwd);
        // 发送加密后的值到服务端
        getRpcProxy(TextFieldServerRpc.class).setText(encryptedPwd);
    }
}
  1. 在Widgetset配置文件中关联服务端与客户端组件:
<replace-with class="com.yourpackage.client.VSecurePasswordField">
    <when-type-is class="com.yourpackage.SecurePasswordField"/>
</replace-with>
  1. 重新编译Vaadin Widgetset,之后在代码中使用SecurePasswordField替代原生PasswordField即可。

注意事项

  • 客户端加密仅解决RPC传输中的明文可见问题,服务端必须对密码进行独立的哈希处理(如BCrypt、Argon2)后存储,不能直接存储客户端加密后的内容。
  • 如果使用HTTPS,传输过程本身是加密的,但RPC payload中仍会存在明文,因此上述方案更贴合你的需求。

内容的提问来源于stack exchange,提问作者Lucas Coelho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 19:15:05