java代码屏蔽 java遮蔽
Java 编程语言中的口令屏蔽
目前 对于 Java 命令行基于文本的输入/输出 API 的批评之一就是它缺乏对命令行输入口令屏蔽的支持 如果借助 AWT/Swing 这便不再成为问题 因为 AWT/Swing 提供了可以提供屏蔽口令的方法
创新互联公司制作网站网页找三站合一网站制作公司,专注于网页设计,成都网站设计、成都做网站,网站设计,企业网站搭建,网站开发,建网站业务,680元做网站,已为1000+服务,创新互联公司网站建设将一如既往的为我们的客户提供最优质的网站建设、网络营销推广服务!
年 月 我发表了本文的早期版本 其后便不断收到大量感谢信 建设性的意见和在应用程序中使用源代码的许可 本文
概述了口令屏蔽描述了用于口令屏蔽的 AWT/Swing 实用程序为命令行输入口令屏蔽问题提供独立于平台的解决方案为口令屏蔽提供一个改进的解决方案(可靠而安全)
口令屏蔽
登录屏幕和登录对话框使用口令屏蔽技术 这种技术要么在输入口令时隐藏口令 要么显示一个字符(比如星号 * )来代替用户输入的字符 例如 当您在一台 Windows 机器上进行登录时 一个登录对话框将会呈现在您眼前 其中的口令一栏使用星号作为屏蔽或回显字符
如果操作系统是 UNIX 则登录屏幕中的口令栏不显示回显字符 它的做法很简单 就是什么都不显示
AWT/Swing 中的口令屏蔽
如果您希望为您的应用程序提供图形化的登录对话框 您可以使用 AWT 的 TextField 类 该类是一个文本组件 允许编辑单行文本 为了屏蔽口令栏 要使用 setEchoChar 方法 例如 为了把回显字符设置为星号 您需要这样做
TextField password = new TextField( );password setEchoChar( * );
基于所使用字体的平均字符宽度 数字 指定了文本栏的宽度 您可以把回显字符设置为任何您喜欢的字符 注意 如果您把它设置为 这意味着输入将会被回显 而不会被屏蔽
在 Swing 中 您可以使用 JPasswordField 它允许编辑单行文本 视图表明正在输入内容 但是不会显示原始字符 JPasswordField 类与和 setEchoChar 一起使用的 AWT 的 TextField 是源代码兼容的 如果您使用 JPasswordField 默认的回显字符是星号 * 但是您可以将其修改为任何您选定的字符 此外 如果您把回显字符设置为 这意味着字符将在输入时显示出来 而不会被屏蔽 图 显示了一个 Swing 登录对话框 其中的回显字符被设置为 # 使用的是下面的代码片断
JPasswordField password = new JPasswordField( );password setEchoChar( # );
命令行输入屏蔽
和 AWT/Swing 不同 在 Java 中没有特殊的 API 可用于屏蔽命令行输入 这也是许多开发人员一直所要求的一项功能 如果您希望为命令行基于文本的 Java 应用程序以及服务器端 Java 应用程序提供一个登录屏幕 它就很有用 提供这种功能的一种方式就是使用 Java 本地接口(Java Native Interface JNI) 对于不了解 C/C++ 或者希望坚持 % 纯 Java 代码的某些 Java 开发人员来说 这可能有一定难度
这里我针对这个问题提出一个解决方案 在本文的早期版本中 所使用的是一个 UNIX 风格的登录屏幕 口令根本不在屏幕上回显 这样做的具体方法是 让一个单独的线程通过重写和打印口令提示命令行 尝试擦除回显到控制台的字符 大家仍然可以从论坛下载该篇文章中专用的代码和改进后的代码
然而 大家最需要的功能之一是使用星号 * 替换回显的字符 因此 本文从为口令屏蔽提供一个简单的解决方案开始 接着给出改进后的 更加可靠和安全的代码
简单的解决方案
这个解决方案使用一个单独的线程 在输入回显字符的时候擦除它们 然后使用星号代替它们 这是使用 EraserThread 类来完成的 如代码示例 所示
代码示例 EraserThread java
import java io *;
class EraserThread implements Runnable { private boolean stop;
/** *@param The prompt displayed to the user */ public EraserThread(String prompt) { System out print(prompt); }
/** * Begin masking display asterisks (*) */ public void run () { stop = true; while (stop) { System out print( \ * ); try { Thread currentThread() sleep( ); } catch(InterruptedException ie) { ie printStackTrace(); } } }
/** * Instruct the thread to stop masking */ public void stopMasking() { this stop = false; }}
注意 这个解决方案广泛利用了线程 然而 如果机器负载很重 就不能确保 MaskingThread 能够足够经常地运行 请继续阅读本文的余下部分来了解代码的改进版本
PasswordField 类使用了 EraserThread 类 这一点在代码示例 中体现出来了 这个类提示用户输入口令 而且 EraserThread 的一个实例尝试使用 * 屏蔽输入 注意 一开始将显示一个星号 (*)
代码示例 PasswordField java
public class PasswordField {
/** *@param prompt The prompt to display to the user *@return The password as entered by the user */ public static String readPassword (String prompt) { EraserThread et = new EraserThread(prompt); Thread mask = new Thread(et); mask start();
BufferedReader in = new BufferedReader(new InputStreamReader(System in)); String password = ;
try { password = in readLine(); } catch (IOException ioe) { ioe printStackTrace(); } // stop masking et stopMasking(); // return the password entered by the user return password; }}
作为如何使用 PasswordField 类的一个例子 考虑应用程序 TestApp 如示例代码 所示 这个应用程序显示一条提示 并等待用户输入口令 当然 输入被屏蔽为星号(*)
代码示例 TestApp java
class TestApp { public static void main(String argv[]) { String password = PasswordField readPassword( Enter password: ); System out println( The password entered is: +password); }}
如果您在 Windows MacOS 或 UNIX 操作系统上运行 TesApp 您将会发现其输出与图 类似 此外还要注意 当您运行该应用程序时 会显示一个初始的星号
使代码安全而可靠
上述的简单解决方案有一个主要缺陷 不应该使用字符串来存储诸如口令这类敏感信息!在本文的余下部分中 将会给出一个经过改进的解决方案
然而 首先 MaskingThread 类能够从几处改进中获益
为了确保跨线程的可见性 尤其是在多 CPU 的机器上 stop 字段应该被标记为 volatile volatile 关键字指定同步线程使用该字段 这样编译器就不会对它进行任何优化 换句话说 应该从内存读取变量的值 而不应该在堆栈中保存任何拷贝
为了确保屏蔽能够在系统高负荷运转时也能够出现 在调用持续期间 调用线程的优先权被设定为最大 返回时再恢复其原始的优先权
代码示例 显示了修订后的 MaskingThread 类 修改的地方均以粗体形式突出显示
import java io *;
/*** This class attempts to erase characters echoed to the console */
class MaskingThread extends Thread { private volatile boolean stop; private char echochar = * ;
/** *@param prompt The prompt displayed to the user */ public MaskingThread(String prompt) { System out print(prompt); }
/** * Begin masking until asked to stop */ public void run() {
int priority = Thread currentThread() getPriority(); Thread currentThread() setPriority(Thread MAX_PRIORITY);
try { stop = true; while(stop) { System out print( \ + echochar); try { // attempt masking at this rate Thread currentThread() sleep( ); }catch (InterruptedException iex) { Thread currentThread() interrupt(); return; } } } finally { // restore the original priority Thread currentThread() setPriority(priority); } }
/** * Instruct the thread to stop masking */ public void stopMasking() { this stop = false; }}
尽管使用 Strings 收集和存储口令看起来似乎很合逻辑 它们并不适合存储诸如口令这样的敏感信息 这是因为 Strings 类型的对象是不可改变的——使用后不能重写或修改字符串的内容 应该使用一个 chars 数组作为代替 修订后的 PasswordField 如代码示例 所示 它是根据 Using Password Based Encryption 改写而来
代码示例 PasswordField java
import java io *;import java util *;
/*** This class prompts the user for a password and attempts to mask input with * */
public class PasswordField {
/** *@param input stream to be used (e g System in) *@param prompt The prompt to display to the user *@return The password as entered by the user */
public static final char[] getPassword(InputStream in String prompt) throws IOException {
MaskingThread maskingthread = new MaskingThread(prompt); Thread thread = new Thread(maskingthread); thread start();
char[] lineBuffer; char[] buf; int i;
buf = lineBuffer = new char[ ];
int room = buf length; int offset = ; int c;
loop: while (true) { switch (c = in read()) { case : case : break loop;
case \r : int c = in read(); if ((c != ) (c != )) { if (!(in instanceof PushbackInputStream)) { in = new PushbackInputStream(in); } ((PushbackInputStream)in) unread(c ); } else { break loop; }
default: if ( room ) { buf = new char[offset + ]; room = buf length offset ; System arraycopy(lineBuffer buf offset); Arrays fill(lineBuffer ); lineBuffer = buf; } buf[offset++] = (char) c; break; } } maskingthread stopMasking(); if (offset == ) { return null; } char[] ret = new char[offset]; System arraycopy(buf ret offset); Arrays fill(buf ); return ret; }}
最后 PasswordApp 类如代码示例 所示 它只是一个用于测试修订后代码的测试应用程序
代码示例 PasswordApp java
import java io *;
lishixinzhi/Article/program/Java/hx/201311/25934
java程序可以屏蔽浏览器长时间没响应的提示吗
不能,java程序不能直接控制浏览器的行为,只能通过浏览器的API来调用浏览器的功能,而浏览器的长时间没响应的提示是浏览器自身的一个功能,java程序无法控制。
java 中怎样将屏蔽掉的代码拆起来
编程的初期可以把checkStyle、findBugs这些都disable掉。因为检查代码都是后期的工作,首先要让程序能够跑起来,然后再考虑效率问题,最后才考虑代码格式等次重要的东西。
一般来说checkStyle的警告都是可以不予理睬的,比如说name hides a field、magic number,对你编程没有影响。但是对开发软件产品来说,这个是最后必须要消除的。因为这将影响你写的代码的可读性,进而影响到将来代码优化和维护。
name hides a field警告指方法的参数和类里面定义的域(或者说是成员变量,数据成员)重名了,换个其他名字就行了,比如说name改为n。
magic number就是指程序里那些不用取变量名,直接把常量值写在使用它的地方的那种数字。这种数字往往让人摸不着头脑,也不知道那是什么意义,就像毫无原因,突然被变出来的一样,所以被称为“魔术数字”。
解决magic number的方法就是把所有用到的常量都声明为public static final,
注释是相当重要的,即使是自己开发的,时间久了也许都会忘记某个变量是用来干什么的……
在JAVA中输入什么代码才能屏蔽非法字符
只能输入数字:“^[0-9]*$”只能输入n位的数字:“^\d{n}$”只能输入至少n位数字:“^\d{n,}$”只能输入m-n位的数字:“^\d{m,n}$”只能输入零和非零开头的数字:“^(0|[1-9][0-9]*)$”只能输入有两位小数的正实数:“^[0-9]+(.[0-9]{2})?$”只能输入有1-3位小数的正实数:“^[0-9]+(.[0-9]{1,3})?$”只能输入非零的正整数:“^\+?[1-9][0-9]*$”只能输入非零的负整数:“^\-[1-9][0-9]*$”只能输入长度为3的字符:“^.{3}$”只能输入由26个英文字母组成的字符串:“^[A-Za-z]+$”只能输入由26个大写英文字母组成的字符串:“^[A-Z]+$”只能输入由26个小写英文字母组成的字符串:“^[a-z]+$”只能输入由数字和26个英文字母组成的字符串:“^[A-Za-z0-9]+$”只能输入由数字、26个英文字母或者下划线组成的字符串:“^\w+$”
标题名称:java代码屏蔽 java遮蔽
文章源于:http://scyanting.com/article/dojscpe.html