在REST应用程序的基本身份验证 [英] Basic authentication in REST-application

查看:250
本文介绍了在REST应用程序的基本身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

环境:


  • JAVA

  • 的Glassfish

  • 在不同的机器REST的服务

  • HTML5的客户端
    AJAX和JQuery

  • 泽西

这是我到目前为止执行:

HTML5客户端###

  $('#btnSignIn')。点击(函数(){
    VAR用户名= $(#用户名)VAL()。
    。VAR密码= $(#密码)VAL();    功能make_base_auth(用户名,密码){
        VAR TOK =用户+:+密码;        VAR最后=基本+ $ .base64.en code(TOK);
        的console.log(FINAL ---->中最后+);
        警报(FINAL ---->中最后+);        最终回报;
    }    $阿贾克斯({
        键入:GET,
        的contentType:应用/ JSON
        网址:HTTP://本地主机:8080 / SesameService / webresources /用户/安全/登录,
        跨域:真实,
        数据类型:TEXT,
        异步:假的,
        数据:{},
        beforeSend:功能(XHR){
            xhr.setRequestHeader('授权',make_base_auth(用户名,密码));
        },
        成功:函数(){
            警报('感谢您对您的登入!');        },
        错误:功能(jqXHR,textStatus,errorThrown){
            的console.log(textStatus,errorThrown);
            警报('签到中的进程错误!!'+ textStatus);
        }
    });
});

服务器

在安全,我没有启用安全管理器,它被禁用!

我已经配置了基本的身份验证Glassfish和我的web.xml看起来像:

< Servlet映射>
    < servlet的名称>&ServletAdaptor LT; / servlet的名称>
    < URL模式> / webresources / *< / URL模式>
< / Servlet映射><安全约束>
    <网上资源收集和GT;
        <网上资源名称>其余各受保护的资源和LT; /网络资源名称>
        <描述/>
        < URL模式> /用户/ * LT; / URL模式>    < /网上资源收集和GT;
    < AUTH约束>
        <角色名称>管理< /角色名称>
        <角色名称>客户与LT; /角色名称>
        <角色名称>用户LT; /角色名称>
    < / AUTH约束>
< /安全约束><登录名,配置>
        < AUTH-方法>&BASIC LT; / AUTH-方法>
        <境界-名称>&jdbcRealm LT; /领域-名称>
    < /登录,配置>
    <安全角色>
        <角色名称>管理< /角色名称>
    < /安全角色>
    <安全角色>
        <角色名称>用户LT; /角色名称>
    < /安全角色>
    <安全角色>
        <描述/>
        <角色名称>客户与LT; /角色名称>
    < /安全角色>

GLASSFISH

LOG

  FINE:[网络安全]设置策略上下文ID:旧= NULL ctxID = SesameService / SesameService
精细:[网络安全] hasUserDataPermission烫发:(javax.security.jacc.WebUserDataPermission/ webresources /用户/安全/登录,GET)
精细:[网络安全] hasUserDataPermission isGranted:真
精细:[网络安全]策略上下文ID是:SesameService / SesameService
精细:[网络安全] hasResource isGranted:真
精细:[网络安全] hasResource烫发:(javax.security.jacc.WebResourcePermission/ webresources /用户/安全/登录,GET)

问:


  1. 如果我加密(不带code)密码的客户,当用户注册和SSL下,其传输/ HTTPS,是实现这个这个安全性好办法吗?


  2. 如果我使用REST的服务没有客户端,它始终是敞开的,为什么呢?没有基本的身份验证?有我明白了一些错误的URL的模式?

     的http://本地主机:8080 / SesameService / webresources /用户/安全/登录


  3. 如果我得到这个工作如何测试,因为现在如果我认证一次,我总是授权?是否有可能退出编程里面的REST的服务或一般如何实施注销?


  4. 在与强制性的base64恩codeD的用户名头使用授权:密码我必须设有code我的用户名和密码到DB呢?我想,并添加编码(允许值是十六进制和Base64编码),以jdbcRealm到GlassFish,似乎密码是足够的,但是当两者连接客户端codeD?

  5. 会发生什么

更新:我改变web.xml和现在直接在浏览器中调用REST服务时,基本的身份验证工作:的http://本地主机:8080 / SesameService /用户/安全/登录

的变化:


  • 我启用了安全管理器中的Glassfish

  • 我改变URL模式


            ServletAdaptor
            / * ---->我把webresources了。它是由生成的Netbeans
         


  • 我改为服务于这个网址:的http://本地主机:8080 / SesameService /用户/安全/登录


现在我得到一个HTTP / 1.1 401试图从HTML5的客户端进行身份验证时,未经授权。

请求头:`

 产地:HTTP://本地主机:8383
主持人:`本地主机:8080`
连接:保持活动
访问控制请求-方法:GET
访问控制请求报头:授权,内容type`

响应:

  X-通电方式:的Servlet / JSP 3.0 / 2.2(GlassFish应用服务器3.1.2.2版的Java /甲骨文公司/ 1.7)
WWW身份验证:基本境界=jdbcRealm
服务器:GlassFish应用服务器3.1.2.2版
编译:无缓存
到期日:星期四,1970年02:00:00 EET 01一月
日期:星期六,2013年4月13日15时25分06秒GMT
内容类型:text / html的
内容长度:1073
缓存控制:无缓存

更新2

当我尝试用JavaScript +授权头我有401错误,并进行身份验证,在日志中:

  FINE:[网络安全]设置策略上下文ID:旧= NULL ctxID = SesameService / SesameService
精细:[网络安全] hasUserDataPermission烫发:(javax.security.jacc.WebUserDataPermission/用户/安全/登录选项)
精细:[网络安全] hasUserDataPermission isGranted:真----> !!!!!!!!!!!!!
精细:[网络安全]策略上下文ID是:SesameService / SesameService
精细:[网络安全] codesource使用Web网址:文件:/ SesameService / SesameService
精细:[网络安全]检查与校长的Web权限:空-------> !!!!!!!
精细:[网络安全]的Web权限=(javax.security.jacc.WebResourcePermission/用户/安全/登录选项)
FINEST:JACC策略提供:PolicyWrapper.implies,上下文(SesameService / SesameService) - 结果是(假)许可((javax.security.jacc.WebResourcePermission/用户/安全/登录选项))
精细:[网络安全] hasResource isGranted:假-------> !!!!!!!!!
精细:[网络安全] hasResource烫发:(javax.security.jacc.WebResourcePermission/用户/安全/登录选项)
FINEST:JACC策略提供:PolicyWrapper.getPermissions(CS),上下文(NULL)codesource((空<没有签名者证书>))权限:java.security.Permissions@5d4de3b0(

* 更新3 的*
我不能谁是试图在跨域情况下,使用基本身份验证的第一个也是唯一的人。
我改变了我的原点十字滤镜这样的:
response.getHttpHeaders()putSingle(访问控制允许报头,授权);

没有401错误了,但还是错误的Ja​​vaScript。 GlassFish中的日志:

  FINEST:JACC策略提供:
getPolicy方法(SesameService / SesameService)不在服务-----> !!!!!!!!
精细:JACC策略提供:文件到达检查类型:授予抵达:虚假的存在:假上次更改时间:0 storedTime:1365968416000状态:删除SesameService / SesameService
精细:JACC策略提供:文件到达检查类型:排除到达:虚假的存在:假上次更改时间:0 storedTime:0状态:删除SesameService / SesameService
精细:TM:getTransaction:TX = NULL,TM = NULL
精细:TM:componentDestroyedorg.apache.catalina.servlets.DefaultServlet@227fe9a8
精细:TM:resourceTable前:0
精细:TM:resourceTable后:0

顺便说一句,因为我从来没有得到这个工作,确实不是调用REST服务直接在自己的领域这一工作方式相同。因此,首先客户端请求,服务器请求和用户名,密码窗口打开,然后客户端请求和服务器进行身份验证和响应的页面?我试图得到它:请求与Authorization头在里面,从从静止服务结果服务器响应,仅此而已。任何想法如何确保REST的服务?比这更容易?这是不可能的。

更新4

我只是想我的HTML5客户端移动到下的Java Web项目,只是纯粹的HTML页面,并在同一域和BASIC认证工作100%。所以原因是因为跨域的环境。


解决方案

  

如果我加密(不带code)如客户密码,当用户注册和SSL传输下它/ HTTPS,是实现这个这个安全和好办法?


最可能的是,你应该简单地传递明文密码通过SSL / HTTPS。

在SSL的所有通信/ HTTPS是加密的,所以它可能不是一个好主意,除非你需要确保Web服务器(技术上的HTTPS终止),以以及加密密码无法看到密码。


  

如果我使用REST的服务没有客户端,它始终是敞开的,为什么呢?没有基本的身份验证?有我明白了一些错误的URL的模式?


不知道我理解这个问题。但是基本认证是不适合的REST认证的良好格局,因为它是纯文本格式传递密码。


  

如果我得到这个工作如何测试,因为现在如果我认证一次,我总是授权?是否有可能退出编程里面的REST的服务或一般如何实施注销?


在基本认证,用户名和密码是由客户端的在每个HTTP请求传递的。如果证书不是由客户端传递,那么服务器拒绝请求。因此没有会​​话的概念。

不过,至于Java EE服务器而言,登录创建用户会话,同一用户以后的请求将使用相同​​的会话。如果你这样配置,本届会议将超时。

如果退出是很重要的(即控制用户会话),那么你必须创建此一个servlet(/注销)的HTTP会话无效。

标准Java安全模型的工作原理如下:在一个安全领域中的用户登录时,Java EE服务器存储在您的浏览器安全cookie。浏览器在每个请求到相同的领域将这个cookie回Java EE服务器。在Java EE服务器检查这个cookie在每一个请求,并用它来识别用户,连接请求发送到用户的会话。

所以,你可能想要做在同一个安全领域的Web应用程序的REST服务,使浏览器和服务器工作的无缝连接。


  

当与强制性的base64恩codeD的用户名头使用授权:密码我必须设有code我的用户名和密码到DB呢?我想,并添加编码(允许值是十六进制和Base64编码),以jdbcRealm到GlassFish,似乎密码是足够的,但是当两者连接客户端codeD?

会发生什么

不,不要带code中的用户名或密码 - 这是所有处理的浏览器和Glassfish深处。如果您在连接客户端code,客户端将连接code编码和服务器将拒绝该密码。



  

你能告诉我,如果是有可能从HTML5的页面中使用j_security_check JavaScript或再次我在的问题:)我已经做情侣Primefaces + JSF的应用程序,我用FORM-auth的,而且没有任何的问题,但这已经完全的灾难情况下我。


您应该能够得到这个与j_security_check假设RESTful服务停留在同一域和安全领域舒适地工作(然后登录到Web应用程序将允许浏览器以正确的cookie发送给REST的URI)。

不过请注意,,其他应用程序将难以访问REST服务。基本上,他们都将通过j_security_check登录,然后通过维持Glassfish的发送的cookie。如果你确实需要其他应用程序以编程方式访问这些服务,则需要另一种解决方案:


  1. 您可以设置安全领域,让不同的鉴定人是'足够';设置HTTP基本认证的以及的,并确保没有被标记为必要的

  2. 部署RESTful服务两次,另一种是不同的URI。如果你想使用HTTP基本身份验证,这可能是一个SSL / HTTPS端点,以确保密码安全地处理

Environment:

  • JAVA
  • Glassfish
  • REST-services in different machine
  • HTML5-client with AJAX and JQuery
  • Jersey

This is what I have implemented so far:

HTML5-client ###

$('#btnSignIn').click(function () {
    var username = $("#username").val();
    var password = $("#password").val();

    function make_base_auth(user, password) {
        var tok = user + ':' + password;

        var final = "Basic " + $.base64.encode(tok);
        console.log("FINAL---->" + final);
        alert("FINAL---->" + final);

        return final;
    }

    $.ajax({
        type: "GET",
        contentType: "application/json",
        url: "http://localhost:8080/SesameService/webresources/users/secured/login",
        crossDomain: true,
        dataType: "text",
        async: false,
        data: {},
        beforeSend: function (xhr) {
            xhr.setRequestHeader('authorization', make_base_auth(username, password));
        },
        success: function () {
            alert('Thanks for your signin in! ');

        },
        error: function (jqXHR, textStatus, errorThrown) {
            console.log(textStatus, errorThrown);
            alert(' Error in signIn-process!! ' + textStatus);
        }
    });
});

SERVER

In Security, I haven't got Security Manager enabled, it is disabled!

I have configured BASIC-authentication to Glassfish and my web.xml looks like that:

<servlet-mapping>
    <servlet-name>ServletAdaptor</servlet-name>
    <url-pattern>/webresources/*</url-pattern>
</servlet-mapping>

<security-constraint>
    <web-resource-collection>
        <web-resource-name>REST Protected resources</web-resource-name>
        <description/>
        <url-pattern>/users/*</url-pattern>

    </web-resource-collection>
    <auth-constraint>
        <role-name>admin</role-name>
        <role-name>customer</role-name>
        <role-name>user</role-name>
    </auth-constraint>
</security-constraint>



<login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>jdbcRealm</realm-name>
    </login-config>
    <security-role>
        <role-name>admin</role-name>
    </security-role>
    <security-role>
        <role-name>user</role-name>
    </security-role>
    <security-role>
        <description/>
        <role-name>customer</role-name>
    </security-role>

GLASSFISH

LOG

FINE: [Web-Security] Setting Policy Context ID: old = null ctxID = SesameService/SesameService
FINE: [Web-Security] hasUserDataPermission perm: ("javax.security.jacc.WebUserDataPermission" "/webresources/users/secured/login" "GET")
FINE: [Web-Security] hasUserDataPermission isGranted: true
FINE: [Web-Security] Policy Context ID was: SesameService/SesameService
FINE: [Web-Security] hasResource isGranted: true
FINE: [Web-Security] hasResource perm: ("javax.security.jacc.WebResourcePermission" "/webresources/users/secured/login" "GET")

QUESTION:

  1. If I encrypt (NOT encode) password in client when user is signing up and transfer it under the SSL/HTTPS, is this secure and good way to implement this?

  2. If I use REST-service without client, it is always open, WHY? No BASIC-authentication? Have I understood something wrong with those url-patterns?

    http://localhost:8080/SesameService/webresources/users/secured/login
    

  3. IF I get this working how to test that, because now if I authenticate once, I am authorised always? Is it possible to "log out" programatically inside the REST-service or in generally how to implement Log out?

  4. When using Authorization in header with mandatory base64-encoded username:password do I have to encode my username and password to DB as well? I tried that and added Encoding (allowed values are Hex and Base64) to jdbcRealm to Glassfish and it seems that password is enough, but what happens when both are encoded in client?

UPDATE: I changed web.xml and now BASIC-authentication is working when calling REST-service straight in browser :http://localhost:8080/SesameService/users/secured/login

Changes:

  • I enabled security manager in Glassfish
  • I changed url-pattern

    ServletAdaptor /*----> I took webresources off. It was generated by Netbeans

  • I changed the url to service to this: http://localhost:8080/SesameService/users/secured/login

Now I get a HTTP/1.1 401 Unauthorized when trying to authenticate from HTML5-client.

Request headers: `

Origin: http://localhost:8383
Host:`localhost:8080`
Connection:keep-alive
Access-Control-Request-Method:GET
Access-Control-Request-Headers:authorization,content-type`

Response:

x-powered-by:Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.2.2 Java/Oracle Corporation/1.7)
WWW-Authenticate:Basic realm="jdbcRealm"
Server:GlassFish Server Open Source Edition 3.1.2.2
Pragma:No-cache
Expires:Thu, 01 Jan 1970 02:00:00 EET
Date:Sat, 13 Apr 2013 15:25:06 GMT
Content-Type:text/html
Content-Length:1073
Cache-Control:no-cache

UPDATE 2

When I try to authenticate with JavaScript + Authorization-header I got 401 error and that in the log:

FINE: [Web-Security] Setting Policy Context ID: old = null ctxID = SesameService/SesameService
FINE: [Web-Security] hasUserDataPermission perm: ("javax.security.jacc.WebUserDataPermission" "/users/secured/login" "OPTIONS")
FINE: [Web-Security] hasUserDataPermission isGranted: true---->!!!!!!!!!!!!!
FINE: [Web-Security] Policy Context ID was: SesameService/SesameService
FINE: [Web-Security] Codesource with Web URL: file:/SesameService/SesameService
FINE: [Web-Security] Checking Web Permission with Principals : null------->!!!!!!!
FINE: [Web-Security] Web Permission = ("javax.security.jacc.WebResourcePermission" "/users/secured/login" "OPTIONS")
FINEST: JACC Policy Provider: PolicyWrapper.implies, context (SesameService/SesameService)- result was(false) permission (("javax.security.jacc.WebResourcePermission" "/users/secured/login" "OPTIONS"))
FINE: [Web-Security] hasResource isGranted: false------->!!!!!!!!!
FINE: [Web-Security] hasResource perm: ("javax.security.jacc.WebResourcePermission" "/users/secured/login" "OPTIONS")
FINEST: JACC Policy Provider: PolicyWrapper.getPermissions(cs), context (null) codesource ((null <no signer certificates>)) permissions: java.security.Permissions@5d4de3b0 (

*UPDATE 3* I can't be the first and only person who is trying to authenticate using BASIC in cross domain case. I changed my cross origin filters like that: response.getHttpHeaders().putSingle("Access-Control-Allow-Headers", "Authorization");

NO 401 error anymore but still error in JavaScript. IN Glassfish log:

FINEST: JACC Policy Provider:
getPolicy (SesameService/SesameService) is NOT in service----->!!!!!!!!
FINE: JACC Policy Provider: file arrival check type: granted  arrived: false exists: false lastModified: 0 storedTime: 1365968416000 state: deleted SesameService/SesameService
FINE: JACC Policy Provider: file arrival check type: excluded  arrived: false exists: false lastModified: 0 storedTime: 0 state: deleted SesameService/SesameService
FINE: TM: getTransaction: tx=null, tm=null
FINE: TM: componentDestroyedorg.apache.catalina.servlets.DefaultServlet@227fe9a8
FINE: TM: resourceTable before: 0
FINE: TM: resourceTable after: 0

BTW, because I have never get this work, does this work same way than calling the REST-service direct in its own domain. So, First client requests, server requests and username-password window opens, then client request and server authenticate and response the page? I am trying to get it: Request with Authorization header in it, response from server with result from the rest service and that's it. Any idea how to secure REST-services? Easier than that? This is impossible.

UPDATE 4

I just tried to move my HTML5-client to under java web-project, just pure html-pages and under same domain and BASIC-authentication is working 100 %. So the reason is because of cross-domain environment.

解决方案

If I encrypt (NOT encode) password in client when user is signing up and transfer it under the SSL/HTTPS, is this secure and good way to implement this?

Most probably you should simply pass the password in plain text over SSL/HTTPS.

All communication in SSL/HTTPS is encrypted, so it's probably not a good idea to encrypt the password as well unless you need to ensure the web server (technically the HTTPS terminator) cannot see the password.

If I use REST-service without client, it is always open, WHY? No BASIC-authentication? Have I understood something wrong with those url-patterns?

Not sure I understand the question. However BASIC auth is not a good pattern for authentication in REST because it is passing the password in plain text.

IF I get this working how to test that, because now if I authenticate once, I am authorised always? Is it possible to "log out" programatically inside the REST-service or in generally how to implement Log out?

In Basic Auth, the username and password are passed by the client in every HTTP request. If the credentials are not passed by the client, then the server rejects the request. As such there is no concept of session.

However, as far as the Java EE server is concerned, the login creates a user session and future requests by the same user will use the same session. If you so configure it, this session will time out.

If logging out is important (i.e. control user sessions), then you have to create a servlet (/logout) for this which invalidates the HTTP session.

The standard Java security model works as follows: When the user logs in to a security realm, the Java EE server stores a secure cookie in your browser. The browser sends this cookie back to the Java EE server in each request to the same realm. The Java EE server checks for this cookie in every request and uses it to identify the user, connecting the request to the user's session.

So you probably want to do have the REST service in the same security realm as the web application, so the browser and server work seamlessly.

When using Authorization in header with mandatory base64-encoded username:password do I have to encode my username and password to DB as well? I tried that and added Encoding (allowed values are Hex and Base64) to jdbcRealm to Glassfish and it seems that password is enough, but what happens when both are encoded in client?

No, don't encode the username or password - this is all handled deep within the browser and Glassfish. If you encode in the client, the client will encode the encoding and the server will reject the password.


Could you tell me if is it possible to use j_security_check from html5-page with javaScript or am I in problems again :) I have made couple of Primefaces + jsf-application where I used FORM-auth and there wasn't any problem, but this has been totally disaster case for me.

You should be able to get this working comfortably with j_security_check assuming that the RESTful services stay in the same domain and security realm (then logging on to the web application will allow the browser to send the correct cookie to the REST URIs).

Do note, however, that other applications will have difficulty accessing the REST services. Basically, they will have to log in via the j_security_check and then maintain the cookies sent by Glassfish. If you do need other applications to access these services programmatically, then you will need another solution:

  1. You can set up the security realm to allow different authenticators to be 'sufficient'; set up HTTP BASIC Auth as well and make sure that none are marked 'necessary'
  2. Deploy the RESTful services twice, the other being a different URI. If you want to use HTTP BASIC Auth, this might be a SSL/HTTPS end point to ensure the passwords are handled securely

这篇关于在REST应用程序的基本身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆