验证码的设计分析

在工作过程中,接手一个项目,项目的登录验证码部分是使用js写的,由js随机生成一个字符串当作验证码。我觉得这样做其实是不合理的。

验证码是,用来区分对方到底是人还是计算机程序而设计的一种验证措施。主要用于阻止垃圾信息,保护网站注册,在线投票系统刷票等等。因此验证码的实质是:用于区分行为方到底是人还是程序。

如果使用js来生成验证码,那么生成方法会暴露给所有人,这不是最主要的。

js生成验证的过程大概是:随机生成一个字符串(当然,在现实的时候,可能会加入css控制其外观,使其眼花缭乱)保存到一个全局变量,当用户提交表单的时候,js会验证用户输入的验证码部分是否和全局变量中保存的字符串相等,如果相等,则将表单”剩余”部分提交给服务器。

问题就在这里,提交表单的时候,并没有提交验证码部分,服务器端根本不关心验证码部分,如果有黑客想写程序进攻系统,在提交表单时,将除验证码之外的“剩余”部分提交给服务器,则完全绕过了验证码。那么,验证码就成了一个“自欺欺人”的,只为了表现给用户看,实际没有作用的废物。


验证码的设计分析_第1张图片


在验证用户输入的验证码时,使用的方法:

验证码的设计分析_第2张图片


这种设计,对计算机程序,完全没有作用。下面我将演示一下为何对程序没有作用。

我们写一段Java程序,使用HttpClient来发送http请求,提交表单:

这里,我们先使用get方法请求一下登录页面:

验证码的设计分析_第3张图片


在控制台打印出的是;


			
		运营安全服务
		
		
		
	
	
	

温馨提示

为了保证您能更好的使用该系统,请您输入正确的用户名与密码。

             客户安全服务管理系统
提  示:
用户名:
密  码:
验证码:

完善您的安全

运营安全服务中心

版权所有@2009集团公司  

这里正是登录页面的html源代码。

接下来,我们使用post方法模拟提交表单:

我们查看登录页面的form,找到form提交的action:

这里action为login.do?method=login

	@Test
	public void testPost() {

		String url = "http://192.168.73.245:8080/twm-manager/login.do?method=login";

		HttpClient httpclient = new DefaultHttpClient();
		HttpPost httppost = new HttpPost(url);
		List formparams = new ArrayList();
		formparams.add(new BasicNameValuePair("userName", "msy"));
		formparams.add(new BasicNameValuePair("accountPassword", "test123"));

		UrlEncodedFormEntity uefEntity;
		
		Header set_cookie = null;
		Header location = null ;
		
		
		try {
			uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8");
			httppost.setEntity(uefEntity);
			System.out.println("executing request " + httppost.getURI());
			HttpResponse response;
			response = httpclient.execute(httppost);
			
			HttpEntity entity = response.getEntity();
			
			System.out.println("response-->" + response.toString());
			
			set_cookie = response.getFirstHeader("Set-Cookie");
			System.out.println("set_cookie : "+set_cookie.getValue());
			
			if(entity != null){
				System.out.println(EntityUtils.toString(entity));
			}
			
			
			
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 关闭连接,释放资源
			httpclient.getConnectionManager().shutdown();
		}
	}


注意:这里我们form表单的参数只有用户名和密码。

控制台打印出获取到的信息:

executing requesthttp://192.168.73.245:8080/twm-manager/login.do?method=login

response-->HTTP/1.1 200 OK[Server: Apache-Coyote/1.1, Set-Cookie: JSESSIONID=AD77010065B4709854D99E78E6AB6A5C;Path=/twm-manager, Content-Type: text/html;charset=utf-8, Content-Length: 824,Date: Thu, 13 Feb 2014 09:32:45 GMT]

set_cookie :JSESSIONID=AD77010065B4709854D99E78E6AB6A5C; Path=/twm-manager




自服务后台管理


  
  
  	 
    
  
  

<body>
</body>


这里得到的是什么,就是登录成功后的首页,从源代码中可以看出首页使用了frame进行布局。可是这里我们并没有涉及到验证码。因此,使用js生成的验证码对计算机程序来说,是无效的。

 

    正确的验证码的应该是,后台生成验证码图片,以流的形式输到前台页面。在提交表单的时候,连验证码一同提交到后台,由后台判断验证码是否正确。这样正确起到验证码的作用。



你可能感兴趣的:(Web前端)