【问题标题】:Implement Authentication for servlet on publish instance CQ5/AEM在发布实例 CQ5/AEM 上实现 servlet 身份验证
【发布时间】:2016-01-21 08:10:25
【问题描述】:

我有一个场景和任何实施建议,这将有很大帮助。我在发布时创建了一个 servlet,它将有来自许多其他第三方应用程序的 POST 请求。此 servlet 仅将传入的发布数据存储在 JCR 中。我已经成功创建了这个 servlet,但现在的要求是确保这个 servlet 安全,以便只有使用特定用户名和密码访问这个 servlet 的应用程序才能被接受。

我能做些什么来实现这个目标?

【问题讨论】:

    标签: authentication servlets aem


    【解决方案1】:

    我会去的方式:

    请那些第 3 方应用程序向您发送用户名和密码,以便您可以在您的 servlet 上验证它们,然后决定您是允许还是拒绝该请求。

    来自 servlet 调用(第 3 方应用程序)

     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // ... 
    
            request.setAttribute("username", "a_valid_user");
            request.setAttribute("password", "a_valid_password");
            request.getRequestDispatcher("yourApp/YourServlet").forward(req, resp);
    }
    

    在您的 servlet 上:

    String username = request.getParameter("username");
    String password = request.getParameter("password");
    
    if("a_valid_user".equals(username) && "a_valid_password".equals(password) {
         // validate and go further
    } else {
         // do not process the request
    }
    

    上面的例子是有效的,以防你可以在你身边验证它们。

    如果此示例无法回答您的问题,请提供有关这些第 3 方应用程序以及您希望验证它们的方式的更多信息。

    【讨论】:

    • 我猜这种方式不太安全。如果有人拦截请求,该密码将对无意的人可见。我一直在寻找更好的方法。
    • 如果您有 https 连接,那么在网络上传输的数据将被加密。
    • 是的@Petre 这就是我的想法。现在,我已将凭据放入与我的 servlet 的连接中的授权中,然后将其编码为 Base64,然后在我的 CQ5 servlet 中,我正在解码授权用户名密码,检查用户在 CQ5 用户中是否有效,然后才返回数据。希望 HTTPS 能够解决凭据嗅探的问题。
    【解决方案2】:

    您可以考虑使用 Google 客户端库。我用它来验证 AEM 发布实例中的用户。第三方服务器通过身份验证后,您可以使用单独的 AEM 服务帐户来处理 POST 处理。

    这是我关于将这些库集成到 AEM 的 SO 帖子。 Google Client API in OSGI

    有了这个,您应该能够设置第三方服务帐户的身份验证...如这里讨论的那样 https://developers.google.com/identity/protocols/OAuth2ServiceAccount

    我实际上还没有在 AEM 中完成服务器到服务器的身份验证,但应该可以。但在一个单独的项目(非 AEM)中,我使用了 Google 客户端库来验证服务帐户。

    【讨论】:

      【解决方案3】:

      我建议使用两步流程:

      • 第一步:认证生成token,也可以使用3rd party service来生成token。
      • 第 2 步:使用此令牌调用您的 servlet,servlet 将首先验证令牌,然后使用发布数据。

      【讨论】:

      • 谢谢先生。实际上对这个东西很陌生,所以真的不知道从哪里开始这个基于令牌的身份验证。但除此之外,您能否查看我回复 Petre 的方法并建议这种方法是否可行,或者那不是推荐的方法?
      • 我阅读了该解决方案并且它是有道理的,但我有点担心由于此类请求 + 身份验证导致服务器过载,您是否确定了您的受众并基于此进行了扩展?您还可以考虑在 apache 级别对此类请求进行身份验证,以便发布服务器仅过滤和更正经过身份验证的请求。
      • 我不需要担心过载,因为只有一个 SAP 应用程序会访问它,这种访问频率并不高。
      【解决方案4】:

      感谢大家的回复。最后,我在 cq 中实现了以下用于身份验证的代码:

                      final String authorization = request.getHeader("Authorization");
                      if (authorization != null && authorization.startsWith("Basic")) {
                        StringTokenizer st = new StringTokenizer(authorization);
                        if (st.hasMoreTokens()) {
                          String basic = st.nextToken();
                          if (basic.equalsIgnoreCase("Basic")) {
                            String decodedStr = Base64.decode(st.nextToken());
                            LOGGER.info("Credentials: " + decodedStr);
                            int p = decodedStr.indexOf(":");
                            if (p != -1) {
                              String login = decodedStr.substring(0, p).trim();
                              String password = decodedStr.substring(p + 1).trim();
      
                              Credentials credentials = new SimpleCredentials(login, password.toCharArray());
                              adminSession = repository.login(credentials);
      
                              if (null != adminSession) {
                                // means authenticated and do your stuff here                                  
                              }
                            }
                          }
                        }
                      }

      同样在调用发布 servlet 的 web 服务代码中,下面是关于我如何在 auth 标头中提供凭据的代码:

                      String authStr = usrname+":"+password;
      				// encode data on your side using BASE64
      				byte[] bytesEncoded = Base64.encodeBase64(authStr.getBytes());
      				String authEncoded = new String(bytesEncoded);		            		           		            		            
      				connection.setRequestProperty("Authorization", "Basic "+authEncoded);
      				connection.setDoOutput(true);      
      				connection.setRequestMethod("POST");      
      				OutputStreamWriter writer = new                 OutputStreamWriter(connection.getOutputStream());  
      				writer.write("jsondata={sample:jsoncontent}");  
      				writer.close();  

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多