Vaadin 7.7.14中如何在v-uiId的RPC中隐藏密码
在Vaadin 7.7.14中避免PasswordField密码明文出现在RPC调用中
Vaadin 7.7.14的默认PasswordField会将输入的密码以明文形式通过RPC同步到服务端,要解决这个问题可以通过以下两种方案:
方案一:手动处理密码提交(无需修改Widgetset)
这种方式绕过Vaadin默认的字段值同步机制,通过自定义JavaScript调用在客户端加密密码后再传递到服务端,避免明文出现在RPC日志中。
- 初始化密码字段并设置唯一ID:
PasswordField senha = new PasswordField("Senha"); senha.setId("secure-password-field"); // 给字段设置ID,方便JS定位
- 创建提交按钮并绑定自定义处理逻辑:
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);" + "});" ); });
- 在服务端注册JavaScript回调,接收加密后的密码:
UI.getCurrent().addJavaScriptFunction("submit-encrypted-pwd", arguments -> { String encryptedPassword = arguments.getString(0); // 在这里处理加密后的密码(比如和服务端存储的哈希值比对) // 注意:客户端加密仅用于RPC传输防明文泄露,服务端仍需独立处理密码哈希存储 });
方案二:自定义PasswordField组件(需编译Widgetset)
通过扩展Vaadin的客户端GWT组件,修改密码同步时的RPC内容,替换明文为加密值。
- 服务端自定义字段类:
public class SecurePasswordField extends PasswordField { // 无需额外逻辑,仅作为客户端组件的服务端关联类 }
- 客户端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); } }
- 在Widgetset配置文件中关联服务端与客户端组件:
<replace-with class="com.yourpackage.client.VSecurePasswordField"> <when-type-is class="com.yourpackage.SecurePasswordField"/> </replace-with>
- 重新编译Vaadin Widgetset,之后在代码中使用
SecurePasswordField替代原生PasswordField即可。
注意事项
- 客户端加密仅解决RPC传输中的明文可见问题,服务端必须对密码进行独立的哈希处理(如BCrypt、Argon2)后存储,不能直接存储客户端加密后的内容。
- 如果使用HTTPS,传输过程本身是加密的,但RPC payload中仍会存在明文,因此上述方案更贴合你的需求。
内容的提问来源于stack exchange,提问作者Lucas Coelho
相关产品推荐
相关产品推荐

