• HTTP的 Basic 验证


    什么是HTTP Basic Authentication?
    在wiki上有详细的解释: http://en.wikipedia.org/wiki/Basic_authentication_scheme
    HTTP Basic Authentication是一个定义在HTTP/1.1规范中的验证机制。这种机制是以用户名和密码为基础的。一个web server要求一个web client去验证一个用户。作为request的一部分,web server 传递被称之为realm的字符串,用户就是在它里面被验证的。注意:Basic Authentication机制的realm字符串不一定反映任何一种安全方针域。Web client得到这些用户名和密码,然后把它传递给web server。Web server然后在一个特定的领域验证这些用户。
    由于密码是使用一种64位的编码来传递,而且目的server没有验证,所以Basic Authentication不是一种安全的验证协议。
    在访问一个需要 HTTP Basic Authentication 的URL的时候,如果你没有提供用户名和密码,服务器就会返回401,
    如果你直接在浏览器中打开,浏览器会提示你输入用户名和密码。
    你可以尝试点击这个url看看效果:http://api.minicloud.com.cn/statuses/friends_timeline.xml  
    如果想要在发送请求的时候添加 HTTP Basic Authentication 认证信息到请求中,有两种方法:  
    一是在请求头中添加Authorization:
    Authorization: "Basic 用户名和密码的base64加密字符串"  
    二是在url中添加用户名和密码:  
    http://userName:password@api.minicloud.com.cn/statuses/friends_timeline.xml  
      
    //需要Base64见:http://www.webtoolkit.info/javascript-base64.html  
    function make_base_auth(user, password) {  
      var tok = user + ':' + pass;  
      var hash = Base64.encode(tok);  
      return "Basic " + hash;  
    }   
      
    var auth = make_basic_auth('QLeelulu','mypassword');  
    var url = 'http://example.com';   
      
    // 原始JavaScript  
    xml = new XMLHttpRequest();  
    xml.setRequestHeader('Authorization', auth);  
    xml.open('GET',url)   
      
    // ExtJS  
    Ext.Ajax.request({  
        url : url,  
        method : 'GET',  
        headers : { Authorization : auth }  
    });   
      
    // jQuery  
    $.ajax({  
        url : url,  
        method : 'GET',  
        beforeSend : function(req) {  
            req.setRequestHeader('Authorization', auth);  
        }  
    }); 
    HTTP基本认证(HTTP Basic Athorization)过程分析
    在HTTP协议进行通信的过程中,HTTP协议定义了基本认证过程以允许HTTP服务器对WEB浏览器进行用户身份证的方法,当一个客户端向HTTP服务 器进行数据请求时,如果客户端未被认证,则HTTP服务器将通过基本认证过程对客户端的用户名及密码进行验证,以决定用户是否合法。
    客户端在接收到HTTP服务器的身份认证要求后,会提示用户输入用户名及密码,然后将用户名及密码以BASE64加密,加密后的密文将附加于请求信息中, 如当用户名为anjuta,密码为:123456时,客户端将用户名和密码用“:”合并,并将合并后的字符串用BASE64加密为密文,并于每次请求数据 时,将密文附加于请求头(Request Header)中。
       HTTP服务器在每次收到请求包后,根据协议取得客户端附加的用户信息(BASE64加密的用户名和密码),解开请求包,对用户名及密码进行验证,如果用 户名及密码正确,则根据客户端请求,返回客户端所需要的数据;否则,返回错误代码或重新要求客户端提供用户名及密码。
    整个交互过程如下(模拟个登录GOOGLE首页的过程,并假设登录GOOGLE需要认证):
    1,客户端向服务器请求数据,请求的内容可能是一个网页或者是一个其它的MIME类型,此时,假设客户端尚未被验证,则客户端提供如下请求至服务器:
    Get /index.html HTTP/1.0
    Host:www.google.com
    这段信息表明,客户端向主机www.google.com请求其位于根目录下的index.html网页,使用http1.0协议。
    2,服务器向客户端发送验证请求代码401,服务器返回的数据大抵如下:
    HTTP/1.0 401 Unauthorised
    Server: SokEvo/1.0
    WWW-Authenticate: Basic realm="google.com"
    Content-Type: text/html
    Content-Length: xxx
    <HTML>
    <HEAD>
        <TITLE>Error</TITLE>
        <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">
    </HEAD>
    <BODY><H1>401 Unauthorised.</H1></BODY>
    </HTML>
    3,当符合http1.0或1.1规范的客户端(如IE,FIREFOX)收到401返回值时,将自动弹出一个登录窗口,要求用户输入用户名和密码。
    4,用户输入用户名和密码后,将用户名及密码以BASE64加密方式加密,并将密文放入前一条请求信息中,则客户端发送的第一条请求信息则变成如下内容:
    Get /index.html HTTP/1.0
    Host:www.google.com
    Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    注:xxxx....表示加密后的用户名及密码。
    5,服务器收到上述请求信息后,将Authorization字段后的用户信息取出、解密,将解密后的用户名及密码与用户数据库进行比较验证,如用户名及密码正确,服务器则根据请求,将所请求资源发送给客户端:
    HTTP/1.0 200 OK
    Server: www.google.com/http1.0
    Content-Type: text/html
    Content-Length: xxxx
    <html>
    网页内容
    </html>
    如用户名及密码不正确,请返回第2步,重新向客户端发送用户验证请求。
    6,在以后的整个通信会话中,客户端均会在请求包中附加入加密后的用户信息。
       HTTP基本认证的目标是提供简单的用户验证功能,其认证过程简单明了,适合于对安全性要求不高的系统或设备中,如大家所用路由器的配置页面的认证,几乎 都采取了这种方式。其缺点是没有灵活可靠的认证策略,如无法提供域(domain或realm)认证功能,另外,BASE64的加密强度非常低,可以说仅 能防止sohu的搜索把它搜到了。当然,HTTP基本认证系统也可以与SSL或者Kerberos结合,实现安全性能较高(相对)的认证系统。
    想起用basic验证的服务器端的设置:
    方式一:在web.xml中配置,可以参考CATALINA_HOME/server/manager/WEB-INF/web.xml
    方式二:在程序中coding,参考如下:
    if(request.getHeader("Authorization")==null){ 
        response.setStatus(401); 
        response.setHeader("WWW-authenticate","Basic realm=\"请输入管理员密码\""); 
    }else if( !(request.getHeader("Authorization").equals(pass))){
        response.setStatus(401);     
        response.setHeader("WWW-authenticate","Basic realm=\"用户名或者密码错误\"");
        out.print("对不起你没有权限!!");
        return;
    }
    GET /manager HTTP/1.0
    Content-Type: application/x-www-form-urlencoded
    Authorization: Basic <base64encode(user:pass)>
    方法一:直接使用new sun.misc.BASE64Encoder().encode(byte[])构造HTTP头
    方法二:  Authenticator.setDefault(new AuthImpl()); 然后使用HttpURLConnection连接即可,这种方式更灵活
    class AuthImpl extends Authenticator {
     protected PasswordAuthentication getPasswordAuthentication() {
      String user = "admin";
      char pass[] = "admin".toCharArray();
    nginx配置
    虽然resin的配置也可以达到效果,但是毕竟是配置到了工程文件中,以后定期更换用户名与密码,都得更新项目描述符;而且有个更要命的问题,如果一个resin上有多个项目的话,一次更新就需要修改所有相关项目的web.xml文件,太麻烦了。在nginx上也可以配置basic认证,而且更简单。
    nginx的http basic认证密码是用crypt(3)加密的,可以试用apache的htpasswd生成密码文件。首先进入apache的安装目录,进入apache/bin/目录下,可以看到htpasswd,输入如下命令生成密码文件。
    htpasswd -c -d pass_file user_name
    其中-c表示生成文件,-d表示是以crypt加密,pass_file是密码文件名,user_name表示basic认证的用户名,回车后会提示输入密码,然后再次输入确认,生成密码文件完成。
    然后就是配置nginx,nginx的认证需要配置到location下,如下所示。
    location ~ /admin/manage {
        auth_basic  "Auth";
        auth_basic_user_file  pass_file;
    }
    其中Auth可以随意设置,它只不过是当需要认证时弹出窗口的服务显示名称而已,pass_file就是我们之前生成的密码文件,这里要注意nginx 0.6.7开始,auth_basic_user_file的相对目录是nginx_home/conf,以前版本的相对目录是nginx_home,现在只要访问包含/admin/manage路径的资源都会弹出认证框,而且对于一个nginx代理了n个web服务的情况,需要更换用户名与密码时,只需要将密码文件替换一次即可,比第一种方式方便可靠了很多。

  • 相关阅读:
    学习之spring属性文件注入
    学习之spring自带缓存
    FreeMarker语法
    spring mvc 拦截器
    spring mvc 全局异常处理
    spring mvc 多视图配置
    学习之spring注解DI疑惑
    @Transactional详解
    mybatis关联查询
    shiro 实现 用户 a 操作b 的权限 ,用户 b 能够及时获知。b不需要退出登陆 。 关闭鉴权缓存,或者不配置缓存
  • 原文地址:https://www.cnblogs.com/lechie/p/2393531.html
Copyright © 2020-2023  润新知