【问题标题】:Logging in Liferay user without password无密码登录Liferay用户
【发布时间】:2024-05-21 06:35:02
【问题描述】:

我需要通过对外部系统进行身份验证来登录 Liferay 中的用户。但是,我仍然需要有一个有效的 Liferay 会话。所以,我需要通过

登录 Liferay
  1. 向用户询问用户名/密码
  2. 使用它们对外部系统进行身份验证。
  3. 仅使用用户名(而不是密码)对 Liferay 登录进行身份验证。
  4. 如果外部系统登录成功,则登录用户。

我做了几件事:

  1. 自动登录
  2. 挂钩到 UserLocalService.authenticateByScreenName 覆盖
  3. auth.pipeline pre 和 check = false
  4. 登录过滤器。

这些都不起作用。以下是对这些方法的解释。这个想法是包括 //如果这些方法有效,将包括调用外部系统进行身份验证。 请纠正我犯错的地方,以及某些方法是否比其他方法更好。

1.自动登录:

一个。设置portal-ext.properties

 auto.login.hooks=com.poc.AutoLoginFil

b.创建一个类

public class AutoLoginFilter implements AutoLogin {

    public AutoLoginFilter() {
        super();
    }

    @Override
    public String[] login(HttpServletRequest req, HttpServletResponse arg1) throws AutoLoginException {

//Call external system to authenticate 
        User user =  UserLocalServiceUtil.getUserByScreenName(company.getCompanyId(), login);
         credentials[0] = String.valueOf(user.getUserId());

        credentials[1] = "undefined";
        credentials[2] = Boolean.TRUE.toString();

            return credentials;
    }
}

c。部署插件项目,重启服务器并访问 http://localhost:8080/web/guest/home 。这应该以 joebloggs 身份登录

这没用

2。挂钩到 UserLocalService.authenticateByScreenName 覆盖

一个。在 liferay-hook.xml 中

<service>
        <service-type>
            com.liferay.portal.service.UserLocalService
        </service-type>
        <service-impl>
            com.test.UserService
        </service-impl>
    </service>

b.扩展 UserLocalServiceWrapper 并使用自定义类。

public class UserService  extends  UserLocalServiceWrapper
{

@Override
    public int authenticateByScreenName(long companyId, String screenName, String password, Map headerMap, Map parameterMap, Map resultsMap)
    {
//Call external system to authenticate 
        String name = "";
        log.info(screenName);
        return SUCCESS;
    }

}

当我登录时,它应该可以使用任何密码。它不是。

3. auth.pipeline pre 和 check = false

一个。在portal-ext.properties

auth.pipeline.enable.liferay.check=false
auth.pipeline.pre=com.test.AutoLoginCustom

b.然后,在

public class AutoLoginCustom implements AutoLogin
{

@Override
public String[] login(HttpServletRequest arg0, HttpServletResponse arg1)
            throws AutoLoginException {

@Override
    public String[] login(HttpServletRequest arg0, HttpServletResponse arg1)
{
//Call external system to authenticate 
  credentials[0] = "joebloggs";

        credentials[1] = "undefined";
        credentials[2] = Boolean.TRUE.toString();

            return credentials;
}

c。部署项目并重新启动服务器。转到http://localhost:8080/web/guest/home。使用用户名和不同的密码登录。它不登录。它甚至没有达到 AutoLoginCustom java 中的调试点。

4.登录过滤器 在 liferay-hook.xml 中,

<servlet-filter>
        <servlet-filter-name>Login</servlet-filter-name>
        <servlet-filter-impl>com.test.AutoLoginFilter</servlet-filter-impl>
    </servlet-filter>

在自动登录过滤器中

public class AutoLoginFil implements Filter
{

    @Override
    public void doFilter(ServletRequest arg0, ServletResponse arg1,
            FilterChain arg2) throws IOException, ServletException {

//Call external system to authenticate 
        log.debug("doFilter");

    }
}

未调用调试过滤器。

这些方法中是否有错误,如果有,错误是什么?是否有不同的方法来做到这一点? 我已经看过以下参考资料。

How do I use autologin in liferay?

Liferay - AutoLogin + Authenticator - Get Credentials From Request Header

【问题讨论】:

    标签: java authentication login liferay hook


    【解决方案1】:

    我又玩了一些,我能够找到解决这个问题的方法。


    的答案 2. 挂钩 UserLocalService.authenticateByScreenName 覆盖

    第一步:

    <service>
            <service-type>
                com.liferay.portal.service.UserLocalService
            </service-type>
            <service-impl>
                com.test.UserService
            </service-impl>
        </service>
    

    第二步:

    扩展 UserLocalServiceWrapper 并使用自定义类。

    public class UserService  extends  UserLocalServiceWrapper
    {
    
    @Override
        public int authenticateByScreenName(long companyId, String screenName, String password, Map headerMap, Map parameterMap, Map resultsMap)
        {
    //Call external system to authenticate 
    
            if(externalAuthenticationSuccess)
            {
              return Authenticator.SUCCESS;
           }
           else
           {
             return Authenticator.FAILURE; 
           } 
    
    }
    

    这在部署时有效。

    当我发布问题时这不起作用,因为:

    1. 我在服务器中有 Tomcat。我在进行此更改之前部署了该项目。
    2. 完成更新后,我使用 Liferay 插件并使用右键单击项目 -> Liferay-> 部署进行部署。
    3. 我在代码中使用断点来查看它是否会在登录期间捕获它。
    4. 这没有被捕获,因为我使用的 Eclipse IDE 需要通过 Server 下的 ReDeploy 而不是 Liferay Plugin 命令部署的项目。

    当我也使用 Eclipse Tomcat 服务器进行部署时,它捕获了断点。

    答案

    1. auth.pipeline pre 和 check = false

      在portal-ext.properties中

      auth.pipeline.enable.liferay.check=false auth.pipeline.pre=com.test.CustomAuthenticator

      public class CustomAuthenticator implements Authenticator
      {
          @Override
          public int authenticateByScreenName(long companyId, String screenName, String password,
                  Map<String, String[]> headerMap, Map<String, String[]> parameterMap) throws AuthException {
      
      
      
          //Call external system to authenticate 
          if(externalAuthenticationSuccess)
          {
              return Authenticator.SUCCESS;
          }
          else
          {
              return Authenticator.FAILURE; 
          } 
      
      
          }
      }
      

    这也有效,但它只在 JBoss 中有效,在 Tomcat 中无效。我在

    中部署了 portal-ext.properties

    TOMCAT_HOME\webapps\ROOT\WEB-INF\classes

    在 JBoss EAP 中,它位于 Liferay_Home 下。它可能没有在 Tomcat 中获得该属性,但在 JBoss 中获得了。

    问题中发布的其他可能的解决方案也可能有效,但我没有探索所有内容以找到配置中的错误。

    如果对这些解决方案有任何意见或问题,请发帖,我很乐意提供进一步的步骤。谢谢你。

    【讨论】:

    • 外部系统调用可以是任何东西(Db、LDAP等)。下面这个例子显示了 ldap 调用 Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://host:port"); env.put(Context.SECURITY_AUTHENTICATION, "简单"); env.put(Context.SECURITY_PRINCIPAL, screenName); //可能需要域 env.put(Context.SECURITY_CREDENTIALS, password); DirContext ctx = new InitialDirContext(env); externalAuthenticationSuccess = (ctx != null);
    • 抱歉格式化。我不知道如何将 cmets 制作为代码,即使我缩进了空格。
    • 我无法让 1 和 4 工作。我不需要第 2 点和第 3 点的自动登录自定义即可工作。抱歉,我无法提供这些步骤。
    • 对于迟到的回复,我深表歉意。是的,我必须调用 user = UserLocalServiceUtil.getUserByScreenName(themeDisplay.getCompanyId(), username);该用户仍然存在于 Liferay 中的 User_ 中。只是没有使用它进行身份验证。
    • 您的意思是添加新用户时?当他们注册时,我们调用常规的 Liferay 注册步骤,除了我们将 autopassword 参数设置为 true。这将让 Liferay 选择一个密码,不管它是什么。用户不会使用它。如果您正在谈论从外部系统导入新用户,是的,我们使用的是注册脚本,它在没有用户参与的情况下进行 Liferay 注册。
    最近更新 更多