通过 SAS Base 上的程序在 SAS 元数据服务器中创建内部帐户

Creating Internal Accounts in SAS Metadata Server by programm on SAS Base

我正在尝试使用 proc metadata 以编程方式创建内部帐户。 下面的代码部分创建了具有外部登录名的人。

put"<Person Name=%str(%')&&PersonName&i.%str(%')>";
   put"<Logins>";
      put"<Login Name=%str(%')Login.&&PersonName&i.%str(%')  Password=%str(%')&&word&i.%str(%')/>";
   put"</Logins>";
put"</Person>";

要创建 ExternalLogin,我们可以设置属性 Password,并且在 SAS 元数据中它将被自动加密。 但是要创建 InternalLogin 类型的对象,必须生成密码的 hash 值和 salt。我知道标准的sas002加密方式,但是在使用proc pwencode的情况下如何获取salt的值?

是否可以使用 SAS Base 创建 InternalLogin?

谢谢。

等等。我找到了一个 article 可以告诉我们如何为这个问题创建存储过程。我的回答是对文章的补充。
该方法基于 sas 程序中的执行 java 方法。

1。 Prereare setPasswd.java class

我修改了文章中的 class。单独的代码连接到元数据服务器并创建 InternalLogin

import java.rmi.RemoteException;
import com.sas.metadata.remote.AssociationList;
import com.sas.metadata.remote.CMetadata;
import com.sas.metadata.remote.Person;
import com.sas.metadata.remote.MdException;
import com.sas.metadata.remote.MdFactory;
import com.sas.metadata.remote.MdFactoryImpl;
import com.sas.metadata.remote.MdOMIUtil;
import com.sas.metadata.remote.MdOMRConnection;
import com.sas.metadata.remote.MdObjectStore;
import com.sas.metadata.remote.MetadataObjects;
import com.sas.metadata.remote.PrimaryType;
import com.sas.metadata.remote.Tree;
import com.sas.meta.SASOMI.ISecurity_1_1;
import com.sas.iom.SASIOMDefs.VariableArray2dOfStringHolder;

public class setPasswd {
  String serverName = null;
  String serverPort = null;
  String serverUser = null;
  String serverPass = null;
  MdOMRConnection connection = null;
  MdFactoryImpl _factory = null;
  ISecurity_1_1 iSecurity = null;
  MdObjectStore objectStore = null;
  Person person = null;

    public int connectToMetadata(String name, String port, String user, String pass){
    try {
            serverName = name;
          serverPort = port;
          serverUser = user;
          serverPass = pass;
      _factory = new MdFactoryImpl(false);
      connection = _factory.getConnection();
      connection.makeOMRConnection(serverName, serverPort, serverUser, serverPass);
      iSecurity = connection.MakeISecurityConnection();
      return 0;

    }catch(Exception e){
      return 1;
    }
    }

    public setPasswd(){};

    public int changePasswd(String IdentityName, String IdentityPassword) {
        try
        {
            //
            // This block obtains the person metadata ID that is needed to change the password
            //
            // Defines the GetIdentityInfo 'ReturnUnrestrictedSource' option.
            final String[][] options ={{"ReturnUnrestrictedSource",""}};
            // Defines a stringholder for the info output parameter.
            VariableArray2dOfStringHolder info = new VariableArray2dOfStringHolder();
            // Issues the GetInfo method for the provided iSecurity connection user.
            iSecurity.GetInfo("GetIdentityInfo","Person:"+IdentityName, options, info);
            String[][] returnArray = info.value;
            String personMetaID = new String();
            for (int i=0; i< returnArray.length; i++ )
            {
                System.out.println(returnArray[i][0] + "=" + returnArray[i][1]);
                if (returnArray[i][0].compareTo("IdentityObjectID") == 0) {
                    personMetaID = returnArray[i][1];
                }
            }
            objectStore = _factory.createObjectStore();
            person = (Person) _factory.createComplexMetadataObject(objectStore, IdentityName, MetadataObjects.PERSON, personMetaID);
            iSecurity.SetInternalPassword(IdentityName, IdentityPassword);
            person.updateMetadataAll();
            System.out.println("Password has been changed.");
            return 0; // success
        }
        catch (MdException e)
        {
            Throwable t = e.getCause();
            if (t != null)
            {
                String ErrorType = e.getSASMessageSeverity();
                String ErrorMsg = e.getSASMessage();
                if (ErrorType == null)
                {
                    // If there is no SAS server message, write a Java/CORBA message.
                }
                else
                {
                    // If there is a message from the server:
                    System.out.println(ErrorType + ": " + ErrorMsg);
                }
                if (t instanceof org.omg.CORBA.COMM_FAILURE)
                {
                    // If there is an invalid port number or host name:
                    System.out.println(e.getLocalizedMessage());
                }
                else if (t instanceof org.omg.CORBA.NO_PERMISSION)
                {
                    // If there is an invalid user ID or password:
                    System.out.println(e.getLocalizedMessage());
                }
            }
            else
            {
                // If we cannot find a nested exception, get message and print.
                System.out.println(e.getLocalizedMessage());
            }
            // If there is an error, print the entire stack trace.
            e.printStackTrace();
        }
        catch (RemoteException e)
        {
            // Unknown exception.
            e.printStackTrace();
        }
        catch (Exception e)
        {
            // Unknown exception.
            e.printStackTrace();
        }
        System.out.println("Failure: Password has NOT been changed.");
        return 1; // failure
    }
}

2。解决依赖

注意 class 中的导入。要启用以下代码,必须设置 CLASSPATH 环境变量。

在 linux 上,您可以在 %SASConfig%/Lev1/level_env_usermods.sh 中添加下一个命令:

export CLASSPATH=$CLASSPATH:%pathToJar%

在 Windows 上你可以 add/change 环境变量 Advanced system settings


那么你应该在哪里搜索jar文件呢?它们在文件夹中:

%SASHome%/SASVersionedJarRepository/eclipse/plugins/

我应该在路径中包含哪些文件?

我已经包含了 OMI 中使用的所有内容 (Open Metadata Interface)。我还添加了 log4j.jar(没有这个 jar 就不能工作。你的提示会很有帮助):

  • sas.oma.joma.jar
  • sas.oma.joma.rmt.jar
  • sas.oma.omi.jar
  • sas.svc.connection.jar
  • sas.core.jar
  • sas.entities.jar
  • sas.security.sspi.jar
  • log4j.jar
  • setPasswd.jar (下一步就是你的 JAR!)

从最近的版本中选择文件。示例:

这里我设置的文件来自 v940m3f(修复版本)。
其他方式是here.

3。编译setPasswd.jar

我试过在 SAS 中使用内部 javac.exe,但它无法正常工作。所以你需要下载JDK来编译jar。我创建了 Bat-file:

"C:\Program Files\Java\jdk1.8.0_121\bin\javac.exe" -source 1.7  -target 1.7 setPasswd.java
"C:\Program Files\Java\jdk1.8.0_121\bin\jar" -cf setPasswd.jar setPasswd.class

Paramethers -source-target 如果您的 JDK 版本更高,在 SAS 中使用,那么参数 -source-target 将有所帮助。 "sas"-java版本你可以通过:

查看
PROC javainfo all;
run; 

在日志中搜索下一个字符串:

java.vm.specification.version = 1.7

4。最后。 SAS 碱基调用

现在我们可以通过此方法调用Java代码(所有方法可用here):

data test;
      dcl javaobj j ("setPasswd");
      j.callIntMethod("connectToMetadata", "%SERVER%", "%PORT%", "%ADMIN%", "%{SAS002}HASHPASSORPASS%", rc1);
      j.callIntMethod("changePasswd", "testPassLogin", "pass1", rc2);
      j.delete();
run;

在日志中:

UserClass=Normal  
AuthenticatedUserid=Unknown  
IdentityName=testPass  
IdentityType=Person  
IdentityObjectID=A56RQPC2.AP00000I  
Password has been changed.  

现在是测试的时候了。创建没有密码的新用户。

执行代码:

data test;
      dcl javaobj j ("setPasswd");
      j.callIntMethod("connectToMetadata", "&server.", "&port.", "&adm", "&pass", rc1);
      j.callIntMethod("changePasswd", "TestUserForStack", "Overflow", rc2);
      j.delete();
run;

现在我们的用户有 InternalLogin 对象。

谢谢。