http://www.blogjava.net/zqli/archive/2006/08/29/66394.aspx
生成有4个随机数字和杂乱背景的图片,数字和背景颜色会改变,服务器端刷新(用history.go(-1)也会变)
原型参考ALIBABA   http://china.alibaba.com/member/showimage

------------产生验证码图片的文件-----image.jsp-------------------------------------------

<%@ page contentType="image/jpeg" import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*" %>
<%!
Color getRandColor(int fc,int bc){//给定范围获得随机颜色
        Random random = new Random();
        if(fc>255) fc=255;
        if(bc>255) bc=255;
        int r=fc+random.nextInt(bc-fc);
        int g=fc+random.nextInt(bc-fc);
        int b=fc+random.nextInt(bc-fc);
        return new Color(r,g,b);
        }
%>
<%
//设置页面不缓存
response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expires", 0);

// 在内存中创建图象
int width=60, height=20;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

// 获取图形上下文
Graphics g = image.getGraphics();

//生成随机类
Random random = new Random();

// 设定背景色
g.setColor(getRandColor(200,250));
g.fillRect(0, 0, width, height);

//设定字体
g.setFont(new Font("Times New Roman",Font.PLAIN,18));

//画边框
//g.setColor(new Color());
//g.drawRect(0,0,width-1,height-1);


// 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到
g.setColor(getRandColor(160,200));
for (int i=0;i<155;i++)
{
        int x = random.nextInt(width);
        int y = random.nextInt(height);
        int xl = random.nextInt(12);
        int yl = random.nextInt(12);
        g.drawLine(x,y,x+xl,y+yl);
}

// 取随机产生的认证码(4位数字)
String sRand="";
for (int i=0;i<4;i++){
    String rand=String.valueOf(random.nextInt(10));
    sRand+=rand;
    // 将认证码显示到图象中
    g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));//调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
    g.drawString(rand,13*i+6,16);
}

// 将认证码存入SESSION
session.setAttribute("rand",sRand);


// 图象生效
g.dispose();

// 输出图象到页面
ImageIO.write(image, "JPEG", response.getOutputStream());


%>

---------------使用验证码图片的文件---------a.jsp------------------------------------

<%@ page contentType="text/html;charset=gb2312" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>认证码输入页面</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">
<META HTTP-EQUIV="Expires" CONTENT="0">
</head>
<body>
<form method=post action="check.jsp">
<table>
<tr>
<td align=left>系统产生的认证码:</td>
<td><img border=0 src="image.jsp"></td>
</tr>
<tr>
<td align=left>输入上面的认证码:</td>
<td><input type=text name=rand maxlength=4 value=""></td>
</tr>
<tr>
<td colspan=2 align=center><input type=submit value="提交检测"></td>
</tr>
</form>
</body>
</html>

-----------------验证的页面----------check.jsp

<%@ page contentType="text/html; charset=gb2312" language="java" import="java.sql.*" errorPage="" %>
<html>
<head>
<title>认证码验证页面</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">
<META HTTP-EQUIV="Expires" CONTENT="0">
</head>

<body>
<%
String rand = (String)session.getAttribute("rand");
String input = request.getParameter("rand");
%>
系统产生的认证码为: <%= rand %><br>
您输入的认证码为: <%= input %><br>
<br>
<%
  if (rand.equals(input)) {
%>
<font color=green>输入相同,认证成功!</font>
<%
  } else {
%>
<font color=red>输入不同,认证失败!</font>
<%
  }
%>
</body>
</html>
代码:
DOWNLOAD /upload/article/a200461101741.rar[/DOWNLOAD]

本页页面地址:

投票评分(记入本贴作者的专家分)

     非常好 还行 一般 扔鸡蛋          投票总得分: 13 / 投票总人次: 6

用户评论列表

#0000 author: 000 submitTime: 2006-00-00 12:59
#1679 评论作者: gree001 发表时间: 2004-08-20 04:58 下午 E-mail: [email protected]

图片没有生成是个红叉。。
这是。。。

#1680 评论作者: gree001 发表时间: 2004-08-20 06:21 下午 E-mail: [email protected]

本机测试通过[windows2000 professional+tomcat4.1.24+jdk1.4.1_02],
  但在199上测试没有通过[redhat linux 7.3+tomcat4.1.24+jdk1.4.2_03],
  应是生成Graphics 对象出错[Graphics g = image.getGraphics();]
请指点。

#1683 评论作者: designlee 发表时间: 2004-08-21 11:00 上午 E-mail: [email protected]

不错,在linux下出问题

#1689 评论作者: gree001 发表时间: 2004-08-23 08:45 上午 E-mail: [email protected]

怎么解决呢?

#1694 评论作者: gree001 发表时间: 2004-08-23 04:35 下午

解决了。linux下用startx启动xwindows测试环境可实现

#1914 评论作者: 是 发表时间: 2004-09-23 12:20 下午

不行啊,是把叉

#1934 评论作者: xiaohanne 发表时间: 2004-09-27 02:43 下午

windows下面应该没问题,可能是烂awt在linux下不能用吧,不行的那位请把你的环境写出来,让我看看

#2059 评论作者: santafeng 发表时间: 2004-10-26 04:40 下午 E-mail: [email protected]

用jbx+resin调试出来是叉,有没有好办法解决?谢谢.

#3188 评论作者: virons 发表时间: 2005-05-14 11:03 上午 E-mail: [email protected]

linux下用startx启动xwindows测试环境可实现,但是如果linux作服务器时会存在一定的安全隐患的,如果服务器重启,还要手动startx一下。不知道有没有更好的办法?

#3201 评论作者: gongjiezi 发表时间: 2005-05-16 04:53 下午 E-mail: [email protected]

windows下测试成功.
非常感谢.
红叉的原因应该是把路径弄错了.
把生成图片的那个jsp写成servlet更好一点.

#3206 评论作者: cedar 发表时间: 2005-05-16 07:28 下午 E-mail: [email protected]

请问如果在linux环境下,要往动态图片上写中文,需要怎么设置呢。尝试了很久,还是弄不出来

#3256 评论作者: 后知后觉 发表时间: 2005-05-21 01:25 下午 E-mail: [email protected]

WINDOWS环境下,很好通过..
谢谢作者...期待ING,你新作品

#3286 评论作者: gree001 发表时间: 2005-05-26 08:45 上午

virons 可以写一个脚本,服务器启动之后,自动启动startx

#3287 评论作者: gree001 发表时间: 2005-05-26 08:46 上午

可以写个脚本,linux重启动的时候,自动执行startx

#4033 评论作者: ssmax 发表时间: 2005-08-11 10:43 上午

红叉是因为linux下面的jsp可能会有几个空行输出,所以干扰了图片的正确字节,图片格式就有问题了,只要把jsp改为servlet就可以解决问题,如果抛出exception就用
-Djava.awt.headless=true
加到服务器jvm启动脚本里面去

import java.io.*;
import javax.servlet.http.*;
import javax.servlet.*;
import java.util.*;

import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
//import com.sun.image.codec.jpeg.*;

public class vImage extends HttpServlet
{
        public void init(ServletConfig conf) throws ServletException
        {
                super.init(conf);
        }
        
        public void doGet(HttpServletRequest req,HttpServletResponse res) throws ServletException, IOException
        {
                res.setContentType("image/jpeg");
                res.setHeader("Pragma","No-cache");
                res.setHeader("Cache-Control","no-cache");
                res.setDateHeader("Expires", 0);
                HttpSession session = req.getSession();
                
                // 在内存中创建图象
                int width=60, height=20;
                BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                
                // 获取图形上下文
                Graphics g = image.getGraphics();
                
                // 生成随机类
                Random random = new Random();
                
                // 设定背景色
                g.setColor(getRandColor(200,250));
                g.fillRect(0, 0, width, height);
                
                // 设定字体
                g.setFont(new Font("Times New Roman",Font.PLAIN,18));
                
                // 画边框
                //g.setColor(new Color());
                //g.drawRect(0,0,width-1,height-1);
                
                // 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到
                g.setColor(getRandColor(160,200));
                for (int i=0;i<155;i++)
                {
                        int x = random.nextInt(width);
                        int y = random.nextInt(height);
                        int xl = random.nextInt(12);
                        int yl = random.nextInt(12);
                        g.drawLine(x,y,x+xl,y+yl);
                }
                
                // 取随机产生的认证码(4位数字)
                String sRand="";
                for (int i=0;i<4;i++)
                {
                    String rand=String.valueOf(random.nextInt(10));
                    sRand+=rand;
                    // 将认证码显示到图象中
                    g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));
                        // 调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
                    g.drawString(rand,13*i+6,16);
                }
                
                // 将认证码存入SESSION
                session.setAttribute("post_validate_code",sRand);
                
                // 图象生效
                g.dispose();
                
                // 输出图象到页面
                ImageIO.write(image, "JPEG", res.getOutputStream());
                //JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(res.getOutputStream());
                //encoder.encode(image);
        }
        
        public void doPost(HttpServletRequest req,HttpServletResponse res) throws ServletException, IOException
        {
                doGet(req,res);
        }
        
        //给定范围获得随机颜色
        private Color getRandColor(int fc,int bc)
        {
                Random random = new Random();
                if(fc>255) fc=255;
                if(bc>255) bc=255;
                int r=fc+random.nextInt(bc-fc);
                int g=fc+random.nextInt(bc-fc);
                int b=fc+random.nextInt(bc-fc);
                return new Color(r,g,b);
    }
}

#4034 评论作者: ssmax 发表时间: 2005-08-11 10:49 上午

红叉是因为linux下面的jsp可能会有几个空行输出(万恶的resin。。。。),所以干扰了图片的正确字节,图片格式就有问题了,只要把jsp改为servlet就可以解决问题,如果抛出exception就用
-Djava.awt.headless=true
加到服务器jvm启动脚本里面去

#4035 评论作者: ssmax 发表时间: 2005-08-11 10:58 上午

看看resin jsp生成的源程序吧(万恶的空行啊),一开头就插3个空行。。。。

pageContext.write(_jsp_string0, 0, _jsp_string0.length);
      pageContext.write(_jsp_string0, 0, _jsp_string0.length);
      pageContext.write(_jsp_string0, 0, _jsp_string0.length);

private static byte []_jsp_string0;
  static {
    _jsp_string0 = "\r\n".getBytes();
  }

#4236 评论作者: SunnyXiao 发表时间: 2005-08-25 02:26 下午

jcaptcha使用起来更方便

#4648 评论作者: ssmax 发表时间: 2005-09-22 12:41 下午

有空看了一下resin的源代码,终于知道resin产生空行的原因:
把jsp解释生成java文件的时候碰到jsp语句就会抽起来解释,可是jsp语句后面的\r\n换行标记(一般大家都有换行吧)就会作为字符输出,所以就造成了输出的换行,比如大家写jsp总有一句<%@ page contentType="text/html;charset=UTF-8" language="java" %>之类的在第一行,之后换行,转成java文件就会输出一个空行了。

上面那个行为是所有服务器都存在的,无论resin或者tomcat都有,区别就在tomcat生成的静态页面是直接out.print的,每次访问内存都要生成一次临时字符,但是resin就会把这些字符作为servlet的变量,这样一个servlet初始化的时候就会生成,并且用远存在,请求的时候输出变量就可以了。

如果你有一个很多字符和程序的页面,使用resin就可以看到有_jsp_string0、_jsp_string1。。。。很多,总之程序段之间的页面字符会一直按序号生成下去。

#6000 评论作者: jackee 发表时间: 2005-11-15 09:59 上午

我的是resion,windows环境,也出现红叉?

#7205 评论作者: bluesky 发表时间: 2005-12-25 10:51 上午

http://blog.csdn.net/ronger924/archive/2004/12/23/226030.aspx

Linux用Java处理图片问题。(http://www.tmingtxing.com)

#8990 评论作者: hotsunn 发表时间: 2006-03-10 03:14 下午

为什么我的老是出现:
org.apache.jasper.JasperException: getOutputStream() has already been called for this response
     我应该怎么改呢?请指教!!!
  

#17000 评论作者: soke128 发表时间: 2006-06-08 07:40 下午 E-mail: [email protected]

谢谢..在Windows下测试成功,没有任何异常

acegi整合CAS

acegi内置了对CAS的支持。这里的CAS是3.0。建立CAS server是一个比较简单的事情。CAS server就是一个标准的war文件,把它发布就可以运行。需要做的仅仅是调整登陆和其他一些页面。先了解一下CAS如何实现SSO。
例子:原有系统A和系统B,现在在它们之间做SSO。
很显然,系统A和B都是CAS client。首先是访问系统A,干掉A的登陆页面,在A的入口判断有没有Ticket(票据),如果没有则重定向到CAS server,在CAS server提供Credential(大多数情况就是用户名和密码)。CAS server的作用非常简单:就是来验证用户密码。正确,则发送Ticket。CAS有5种Ticket,分别是TGC(通过cookie发送的ticket),ST(Service Ticket),PGT,PGTIOU,PT。其中PGT,PGTIOU,PT属于代理ticket,这里不作讨论。具体可以参考
http://www.blogjava.net/openssl/archive/2006/04/26/SSO_CASProxy.html
TGC和ST的关系可以打个比方:
我去中央电视塔去玩,结果发现地下还有个海底世界。SSO前我是这么玩的:先去电视塔买张门票,玩完了;再去海底世界买张门票,玩完了。发现真累,两个景点这么近还要买两次门票,就不能搞个通票吗?于是就SSO。于是这样:我先去电视塔,门卫告诉我你不能进去要买票,于是把我送到通票售票处(CAS server)买票(登录),买吧,于是给了我两张票,注意,是两张,一张发到我手里,上面写着仅限电视塔使用(ST);靠,不是通票吗,咋仅限电视塔使用?别急,还有一张票(TGC)通过cookie发送你看不见。人家说了保证没问题,我咋办,这是人家的规矩,那就先去玩吧。出了电视塔我直扑海底世界,
门卫说要海底世界票,不会吧,我买的通票啊,门卫说不着急,又把我送回通票售票处(CAS server),通票售票处(CAS server)一看,发现我有TGC,嘿嘿,这家伙买过票了不用再买(不用再登录),于是换我一张票(ST)上面写着仅限海底世界使用,于是我就拿着这张票又去海底世界了。于是我明白了啥是SSO了,不就是把买票改成换票了吗?
比方完了,最开始的例子也就不往下继续了。需要注意的是系统A和B整合SSO需要把A、B的用户密码集中管理,你说A中我的用户名是张三,B中是李四,SSO能不能帮我自动识别,回答是不行的。
继续Acegi的整合。
CAS server是做用户密码验证,具体的权限授权的工作还是在各个单个系统里,也不应该交给它管。做用户密码验证需要AuthenticationHandler。这个具体就是根据Credential返回一个boolean值来判断你输入的用户密码正不正确。acegi提供了一个实现。
以一个典型的web访问来说明整个过程
1、用户访问一个受acegi安全保护的页面或业务方法;
2、用户没有登陆的话显然会抛出AuthenticationException
3、配置exceptionTranslationFilter捕获这个异常重定向到CAS server登陆页面

        < bean  id ="exceptionTranslationFilter"  class ="org.acegisecurity.ui.ExceptionTranslationFilter" >
            
< property  name ="authenticationEntryPoint" >< ref  local ="casProcessingFilterEntryPoint" /></ property >
        
</ bean >
        
        
< bean  id ="casProcessingFilterEntryPoint"  class ="org.acegisecurity.ui.cas.CasProcessingFilterEntryPoint" >
            
< property  name ="loginUrl" >< value > https://my.company.com/cas/login </ value ></ property >
            
< property  name ="serviceProperties" >< ref  local ="serviceProperties" /></ property >
        
</ bean >
        
        
< bean  id ="serviceProperties"  class ="org.acegisecurity.ui.cas.ServiceProperties" >
            
< property  name ="service" >< value > https://server.company.com/myapp/j_acegi_cas_security_check </ value ></ property >
            
< property  name ="sendRenew" >< value > false </ value ></ property >
        
</ bean >

serviceProperties里的service属性即在CAS server登陆完毕后由CAS server重定向回来的页面
  https://my.company.com/cas/login?service=https%3A%2F%2Fserver.company.com%2Fmyapp%2Fj_acegi_cas_security_check
4、CAS server检查是否有TGC ,没有则登陆,登陆后返回。这里屁股后面跟着的即ST,TGC通过cookie一并发送到客户端。
   https://server.company.com/myapp/j_acegi_cas_security_check?ticket=ST-0-jhsdfguwgeds
5、配置casProcessingFilter来处理返回ST(和以前的authenticationProcessingFilter比较类似)

    < bean  id ="casProcessingFilter"  class ="org.acegisecurity.ui.cas.CasProcessingFilter" >
        
< property  name ="authenticationManager" >< ref  local ="authenticationManager" /></ property >
        
< property  name ="authenticationFailureUrl" >< value > /casfailed.jsp </ value ></ property >
        
< property  name ="defaultTargetUrl" >< value > / </ value ></ property >
        
< property  name ="filterProcessesUrl" >< value > /j_acegi_cas_security_check </ value ></ property >
    
</ bean >

6、配置authenticationManager

    < bean  id ="authenticationManager"  class ="org.acegisecurity.providers.ProviderManager" >
      
< property  name ="providers" >
         
< list >
            
< ref  local ="casAuthenticationProvider" />
         
</ list >
      
</ property >
   
</ bean >
   
  
< bean  id ="casAuthenticationProvider"  class ="org.acegisecurity.providers.cas.CasAuthenticationProvider" >
        
< property  name ="casAuthoritiesPopulator" >< ref  local ="casAuthoritiesPopulator" /></ property >
        
< property  name ="casProxyDecider" >< ref  local ="casProxyDecider" /></ property >
        
< property  name ="ticketValidator" >< ref  local ="casProxyTicketValidator" /></ property >
        
< property  name ="statelessTicketCache" >< ref  local ="statelessTicketCache" /></ property >
        
< property  name ="key" >< value > my_password_for_this_auth_provider_only </ value ></ property >
    
</ bean >  

具体作用的是casAuthenticationProvider,casAuthenticationProvider通过 casProxyTicketValidator来校验ST

     < bean  id ="casProxyTicketValidator"  class ="org.acegisecurity.providers.cas.ticketvalidator.CasProxyTicketValidator" >
        
< property  name ="casValidate" >< value > https://my.company.com/cas/proxyValidate </ value ></ property >
        
< property  name ="serviceProperties" >< ref  local ="serviceProperties" /></ property >
    
</ bean >  

casProxyTicketValidator又具体实现调用了CAS Client library里的ProxyTicketValidator校验ST,ProxyTicketValidator 就比较有意思了,它做了个HTTPS请求CAS server,结果还是CAS server来校验ST(绕了一大圈)
 https://my.company.com/cas/proxyValidate?service=https%3A%2F%2Fserver.company.com%2Fmyapp%2Fj_acegi_cas_security_check
 重新回到CAS server,它接受到这个HTTPS请求,检查ST是否与对这个service发行的ST吻合,吻合的话CAS server就会发回一个肯定的XML回复,里面包含了用户名(username)。剩下的就EASY了,casProxyTicketValidator解析XML,casProxyDecider处理代理,casAuthoritiesPopulator根据解析后的XML获得user,最后就是casAuthenticationProvider构造Authentication(这里是CasAuthenticationToken)
7、重新回到casProcessingFilter,它将Authentication放入HttpSession
这样就完成了整个过程

http://www.blogjava.net/RongHao/archive/2006/08/29/66389.html



Uche Ogbuji ([email protected]), 首席顾问, Fourthougth, Inc.

2006 年 7 月 31 日

拥有大量预算作为后盾的 Web 设计人员可以获得任何所需的资源,从而可以把他们的想像力付诸于 Web 体验。他们可以聘请专业摄像师来制作引人注目的照片;可以请最好的 HTML 和 CSS 专家来创建适用于多种浏览器的复杂布局;可以指导图形艺术家根据企业服装来创作华丽的装饰物;可以聘请专业文案人员起草迷人的散文。最大的好处是,他们能雇佣大量测试用户和关注小组来确保网站吸引人、便于使用并能按照预期进行工作。

但是,并不是所有的 Web 设计人员都这样幸运!不幸的是,有些设计人员必须用很少的钱来创建网站,并且对 Web 体验的预期并不见得很低。在这种情况下,您必须寻求一切可以获得的帮助。多半来说,Web 开发人员和设计人员在与同事共享知识和成就方面是非常慷慨的。当您共享时,同事们通常会努力地纠正并增强您的作品,使其变得更加精致、bug 更少,并会提供您自己的关注小组和质量保证。这意味着您可以找到大量免费材料。如果您知道去哪里找的话,就可以填补低预算 Web 开发运营情况下的一些漏洞。在本文中,我将介绍各类免费的 Web 资源,以及对一些貌似免费,实其不然的 Web 资源的警告。

创造性的公用

首先介绍 Creative Commons(CC),它本身不是免费资源的来源,而是提供免费资源的人们所使用的许可证的来源。用他们自己的话说:CC 是一个非营利性组织,为创造性作品提供灵活的版权许可。您可以选择一个 CC 许可,以允许所有者要求您在使用所有者的作品或修改他们的作品时给予他们荣誉(归属条款);可以限制自己作品仅用于非营利性组织;可以要求任何对您作品所作的更改必须在与原条款相同的条款下共享(类似共享的条款)。还有其他条款,您可以组合这些条款。例如,一个常见的 CC 许可是Attribution Share Alike 许可。

CC 已取得了巨大成功 —— 来自 CC 许可的作品主体十分庞大,并且每天都在扩大。文学、图像、音乐等作品都可以在 CC 许可下提供。只要满足限制,您可以自由地在网站上使用任何这些作品。要了解如何找到 Web 设计的任何免费产品,第一步是了解如何搜索在 CC 许可下提供的材料。您可以使用 CC 搜索引擎页面直接获得来源,这允许您利用搜索引擎(如 Google 和 Flickr)和免费资源收集(如 Flick 和 DMusic) 的专业搜索功能。

样式元素

好的样式表是好网站的骨架 —— 尤其是层叠样式表 (CSS)。不幸的是,浏览器中多变的支持意味着很难开发好的样式表。依靠免费样式表,至少是样式元素的免费模块,您可以省去大量精力和测试工作。许多站点提供 CSS 说明和示例,但我的关注点是我找到的站点,大多数都有 CSS 材料,您可以用于快速地组装成自己的站点。有一个由顶级 Web 专业人士开办的以期刊形式出现的站点:A List Apart,着重于 Code 和 Design 主题。CSS Intensivstation Templates 专注于几个用于结构化站点的主要的布局样式。

最有名的 CSS 交换地是 CSS Zen Garden,但您在使用此网站时必须格外小心。CSS Zen Garden 旨在展示 CSS 的强大功能。CSS 是分离内容和形式的好方法。但起初许多 Web 开发人员回避 CSS,因为他们认为如果不用传统的 HTML 技巧(如布局表格和隐藏图像),就创建不出同样令人难忘的效果。CSS Zen Garden 通过漂亮的样式证明这一认识是错误的。其中有一个单独且共享的内容片段,Web 设计人员创建了页面来以某种独特方式显示这些内容。他们使用巧妙的布局、迷人的图像和颜色,通常创作出某种主题,如大海或博物馆风格的主题。CSS Zen Garden 不能作为模板的集合。您可以在大多数 CSS 贡献中显示的警告中看到以下说明:

此设计不是模板。未经设计者的书面许可,不得复制。但是,可以随意研究 CSS 并在其他地方使用学到的技术。

此外,许多贡献者使用非免费的图像。站点维护人员请求贡献者在非商业 Creative Commons 许可下提供他们的 CSS(参见 参考资料),所以复制 CSS 通常是安全的做法,但要确保检查贡献者 CSS 文件的开头部分。

图像

专业网站会使用各种图像,从照片到艺术家的绘画到图标和符号,等等。一些站点提供免版税的图像。有一个项目值得您关注,即 Open Clip Art Library,它是一个贡献的、可下载的剪贴画的集合。图像的范围包括从小而简单的图像到大而复杂的图像。大多数图像是可缩放矢量图形 (SVG) 格式,它是一种开放的、基于 XML 的格式。SVG 增强了对浏览器的支持,但它尚不通用,所以 Open Clip Art Library 包括每个图像的 PNG 版本。您可以浏览或搜索网站上的图像,但可能只想下载一个发行版,所以可以脱机浏览。图形的质量类似于您在商店购买的许多剪贴画集合中找到的图像的质量。当我需要符号、图标和其他资源(如高亮显示)时,通常会浏览 Open Clip Art Library,但 MaxPower Free Icons 是一组很好的到免费图标集合的链接。说到商店里的剪贴画集合,即使已经购买,仍有许多限制。一些剪贴画需要商业使用版税。如果购买此类集合,请确保检查 End User License Agreements。

当需要照片时,我经常会访问前面提到过的 Flickr 的 CC 照片库,但是我通常是通过 Yotophoto 到达那里的,Yotophoto 是从 CC 变体到 Public Domain 的一个免费许可照片的搜索聚合地。我最喜欢的一个资源站点是 stock.xchng。此站点包括大量极高品质的照片,并有一个非常好用的搜索引擎。不是所有的照片都是免版税的,但大多数是!您甚至可以查看是否有照片的模型发行,这是决定使用包含人像的照片时要考虑的一个重要因素。一个规模较小、尚不精致,但仍十分有用的站点是 Open Photo,它只包含经 CC 许可的照片。我还使用 MorgueFile,这个站点类似于 stock.xchng 站点,具有搜索和丰富元数据方面的类似优点。MorgueFile 上的所有图像受到专门许可(不基于 CC)的约束,但免除了个人或商业作品的版税。我喜欢 MorgueFile FAQ 中针对他们为什么提供免费图像的解答: 此网站遵循传统的万维网。它致力于倡导自由观点和交换。

设计工具

一些 Web 设计人员和公司提供联机工具来帮助其他用户并提高他们自己的社区形象。最常用的是颜色方案工具,它允许您为自己的站点选择富有美感的、令人愉快的一组颜色。在搭配颜色方面,我的确没有世上最好的眼力,所以我感谢诸如 Wellstyled.com 的 Color Scheme Generator 这样的网站。另一个提供更多有关如何组装方案的站点是 SiteProCentral.com's HTML Color Code Combination Chooser。

最流行的 Web 浏览器也是最奇怪的浏览器。多年来,Web 设计人员不得不应对 Microsoft Internet Explorer 5 和 6,包括 Macintosh 和 Windows 版本之间的差异。Microsoft 正在开发 7 版浏览器,他们承诺新版本具有更好的标准兼容性,但是另一方面 Dean Edwards 已经开发了 JavaScript 解决方案。引用该网站的话:

[Dean Edwards'] IE7 是一个 JavaScript 库,使 IE 的行为像标准兼容的浏览器。它修复了许多 CSS 问题并使透明 PNG 在 IE5 和 IE6 下正常工作。

当您设计网站时,记住 Macintosh 用户是十分重要的。如果购买测试用的 Mac 机不是一个选择的话,您应感谢 Daniel Vine,因为他创建了 iCapture。您可以在此站点指定 URL、搜索看上去像 Mac 机上的 Safari Web 浏览器显示的 PNG 图像。Edwards 还提供 ieCapture,允许查看您的站点在 Macintosh IE7 beta 中的显示效果。

完全 Web 布局和模板

有时即使获得以上所有帮助,我还是不能创建引人注目的网页。我可能想要一切,幸运的是可以在一些网站中找到免费的完整页面布局,包含 HTML(经常是 XHTML)模板、图形、样式表、高亮显示等。Open Web Design 有近 2000 个各种品质的完整模板。该网站有一个评级系统,有时会进行设计人员竞赛来扩大其收集量。Open Source Web Design 是一个具有类似规模的网站。 

结束语

在本文中,您了解了许多资源,可以从中获得免费资料和工具以改进您的网站。即使您有预算来得到顶级的专业帮助,如果熟悉 Web 设计的最新技术,还是会很有帮助的。所幸的是,最新技术几乎不被隐藏或无法访问,它们总是免费的。如果有机会,我还鼓励您进行共享,比如为我提到的网站做贡献。毕竟,Web 美学的浪潮会水涨船高