代码之家  ›  专栏  ›  技术社区  ›  TM00

Dropwizard身份验证标头令牌

  •  1
  • TM00  · 技术社区  · 7 年前

    我正在尝试在Dropwizard web应用程序中实现OAuth2身份验证。我已创建所需的 Authenticator Authorizer 类并添加了 Dropwizard manual 在我的应用程序的run方法中,如下所示:

    environment.jersey().register(new AuthDynamicFeature(
                    new OAuthCredentialAuthFilter.Builder<User>()
                    .setAuthenticator(new TokenAuthenticator(service))
                    .setAuthorizer(new TokenAuthorizer())
                    .setPrefix("Bearer")
                    .buildAuthFilter()));
            environment.jersey().register(RolesAllowedDynamicFeature.class);
            //If you want to use @Auth to inject a custom Principal type into your resource
            environment.jersey().register(new AuthValueFactoryProvider.Binder<>(User.class));
    

    我所需的行为是,在我的客户端通过在我的登录页面上提供其凭据登录后,我想将客户端重定向到我使用Dropwizard视图创建的问候页面,该页面位于路径“/我”下,如下所示:

    //After succesfull login and token generation
    return Response.seeOther(new URI("/me")).build(); // redirect to greeting page
    

    我的问候资源如下所示:

    @Path("/me")
    @Produces(MediaType.TEXT_HTML)
    public class UserResource {
    
        @GET
        public UserView getView(@Auth User user) {
                return new UserView(user);
        }
    
    }
    

    目前,我获得了“访问此资源需要凭据”登录后的响应。阅读令牌身份验证后( nice explanation here )我发现必须在每个请求的标头中从客户端发送令牌。因此,我的问题是如何告诉用户的浏览器(客户端)在未来请求的标头中包含令牌?

    1 回复  |  直到 7 年前
        1
  •  0
  •   TM00    7 年前

    我通过以下方式解决了这个问题:

    为了验证用户,必须在请求的标头中以以下形式发送令牌 Authorization: Bearer <token-value> . 此令牌由服务器在身份验证时发送,并且必须由客户端/用户存储,以便在将来的请求中发送。在提交登录表单时,我使用ajax请求存储了令牌,如下所示:

    <#-- Handle form submission response to save the token on the client side-->
    <script>
        $('#loginForm').submit(function(event){
            event.preventDefault();
            $.ajax({
              url: $(this).attr('action'),
              type: 'POST',
              data : $(this).serialize(),
              dataType: 'json',
              success: function(data){
                //alert("The server says success!!: " +data);
                console.log(data);
                window.sessionStorage.accessToken = data.token;
                window.location = data.url;
    
              },
              error: function(data){
                alert("The server says error! : ");
                console.log(data);
              }
            });
    });
    </script>
    

    然后,登录资源生成JSON,JSON在上述代码的数据变量中接收。所需的令牌驻留在数据中。令牌-然后存储。我在JSON中添加了第二个名为“url”的条目,以指示成功身份验证后要重定向到的路径。

    现在,当需要时,令牌存储在客户端。为了在请求头中发送这个令牌,我需要改变使用Dropwizard提供的视图的方法。我没有直接要求身份验证,而是将视图的资源和经过身份验证的数据资源分开。要澄清,请考虑以下示例。用户登录,获取令牌,然后转到显示其用户名的页面。对于页面,将使用创建视图资源。ftl文件用作模板。类似于:

    @Path("/me")
    @Produces(MediaType.TEXT_HTML)
    public class UserResource {
    
    
        @GET
        public UserView getView() {
           return new UserView();
    
        }
    }
    

    public class UserView extends View {
    
        public UserView() {
            super("user.ftl");
    
        }
    }
    

    和用户。ftl:

    <#include "include/head.html">
    <#include "include/header.html">
    
    <!-- Header --> 
    <div id ="headerWrapper">
    </div>
    
    <div class="container-fluid">
    
    <div id="name">
        <p>Hello user</p>
    </div>
    
    </div>
    
    <#include "include/footer.html">
    

    现在,为了检索用户名,我创建了一个新资源,它在新路径上生成JSON。例如:

    @Path("/getdetails")
    @Produces(MediaType.APPLICATION_JSON)
    public class UserDetailsResource {
    
        @GET
        @Timed
        @UnitOfWork
        public User getDetails(@Auth User user) {
    
            return user;
        }
    
    }
    

    此资源需要身份验证,并提供可从中检索用户名的JSON。现在,要获取用户名并将其放置在视图中,只需向 users.ftl 通过对getdetails资源的ajax请求,在标头中提供令牌,并使用结果将用户名放置在视图中。请参见下面的脚本。

    <script>
    
      $.ajax({
              url: '/getdetails',
              type: 'GET',
              headers: {"Authorization": window.sessionStorage.accessToken},
              dataType: 'json',
              success: function(data){
                //alert("The server says success!!: " +data);
                console.log(data);
                $("#name").text('Hello '+data.username);
              },
              error: function(data){
                alert("The server says error! : ");
                console.log(data);
              }
            });
    
    </script>