JAAS ConfigFile

BeginJava

Mitglied
Hallo, ich habe mal eine Frage.
und zwar versuche ich gerade mich in Jaas einzuarbeiten aber bekomme immer einen Fehler.
Und zwar:
Cannot create LoginContext. Anmeldekonfiguration kann nicht gefunden werden.

Ich benutze das JAAS Authentication Tutorial von Oracle
Fogende Klassen habe ich:

Die klasse mit der Main, die auch den CallBackHandler Implememntiert:
Java:
//stimmen folgende 5 Behauptdungen? 

//subject = User
//Principal = sowas wie userID
//NameCallback = Name 
//PasswordCallback = Passwort 
//TextOutputCallback = warning, errors, ... an den user ausgeben.


package sample;

import java.io.*;
import java.util.*;
import javax.security.auth.login.*;
import javax.security.auth.*;
import javax.security.auth.callback.*;

/**
 * <p> This Sample application attempts to authenticate a user
 * and reports whether or not the authentication was successful.
 */
public class SampleAcn {

   /**
    * Attempt to authenticate the user.
    *
    * <p>
    * 
    * @param args input arguments for this application.  These are ignored.
    */
    public static void main(String[] args) {

	// Obtain a LoginContext, needed for authentication. Tell it 
	// to use the LoginModule implementation specified by the 
	// entry named "Sample" in the JAAS login configuration 
	// file and to also use the specified CallbackHandler.
	LoginContext lc = null;
	try {
	    lc = new LoginContext("Sample", new MyCallbackHandler());
	} catch (LoginException le) {
	    System.err.println("Cannot create LoginContext. "
	        + le.getMessage());
	    System.exit(-1);
	} catch (SecurityException se) {
	    System.err.println("Cannot create LoginContext. "
	        + se.getMessage());
	    System.exit(-1);
	} 

	// the user has 3 attempts to authenticate successfully
	int i;
	for (i = 0; i < 3; i++) {
	    try {

		// attempt authentication
		lc.login();

		// if we return with no exception, authentication succeeded
		break;

	    } catch (LoginException le) {

		  System.err.println("Authentication failed:");
		  System.err.println("  " + le.getMessage());
		  try {
		      Thread.currentThread().sleep(3000);
		  } catch (Exception e) {
		      // ignore
		  } 
	
	    }
	}

	// did they fail three times?
	if (i == 3) {
	    System.out.println("Sorry");
	    System.exit(-1);
	}

	System.out.println("Authentication succeeded!");

    }
}


/**
 * The application implements the CallbackHandler.
 */
class MyCallbackHandler implements CallbackHandler {

    /**
     * Invoke an array of Callbacks.
     *
     * <p>
     *
     * @param callbacks an array of <code>Callback</code> objects which contain
     *			the information requested by an underlying security
     *			service to be retrieved or displayed.
     *
     * @exception java.io.IOException if an input or output error occurs. <p>
     *
     * @exception UnsupportedCallbackException if the implementation of this
     *			method does not support one or more of the Callbacks
     *			specified in the <code>callbacks</code> parameter.
     */
    public void handle(Callback[] callbacks)
    throws IOException, UnsupportedCallbackException {
      
	for (int i = 0; i < callbacks.length; i++) {
	    if (callbacks[i] instanceof TextOutputCallback) {
      
		// display the message according to the specified type
		TextOutputCallback toc = (TextOutputCallback)callbacks[i];
		switch (toc.getMessageType()) {
		case TextOutputCallback.INFORMATION:
 		    System.out.println(toc.getMessage());
 		    break;
 		case TextOutputCallback.ERROR:
 		    System.out.println("ERROR: " + toc.getMessage());
 		    break;
 		case TextOutputCallback.WARNING:
 		    System.out.println("WARNING: " + toc.getMessage());
 		    break;
 		default:
 		    throw new IOException("Unsupported message type: " +
 					toc.getMessageType());
 		}
 
 	    } else if (callbacks[i] instanceof NameCallback) {
  
 		// prompt the user for a username
 		NameCallback nc = (NameCallback)callbacks[i];
  
 		System.err.print(nc.getPrompt());
 		System.err.flush();
 		nc.setName((new BufferedReader
			(new InputStreamReader(System.in))).readLine());
 
 	    } else if (callbacks[i] instanceof PasswordCallback) {
  
 		// prompt the user for sensitive information
 		PasswordCallback pc = (PasswordCallback)callbacks[i];
 		System.err.print(pc.getPrompt());
 		System.err.flush();
 		pc.setPassword(readPassword(System.in));
  
 	    } else {
 		throw new UnsupportedCallbackException
 			(callbacks[i], "Unrecognized Callback");
 	    }
	}
    }
   
    // Reads user password from given input stream.
    private char[] readPassword(InputStream in) throws IOException {
	
	char[] lineBuffer;
	char[] buf;
	int i;

	buf = lineBuffer = new char[128];

	int room = buf.length;
	int offset = 0;
	int c;

loop:	while (true) {
 	    switch (c = in.read()) {
 	    case -1:
 	    case '\n':
		break loop;

 	    case '\r':
 		int c2 = in.read();
 		if ((c2 != '\n') && (c2 != -1)) {
 		    if (!(in instanceof PushbackInputStream)) {
 			in = new PushbackInputStream(in);
 		    }
 		    ((PushbackInputStream)in).unread(c2);
 		} else
 		    break loop;

 	    default:
 		if (--room < 0) {
 		    buf = new char[offset + 128];
 		    room = buf.length - offset - 1;
 		    System.arraycopy(lineBuffer, 0, buf, 0, offset);
 		    Arrays.fill(lineBuffer, ' ');
 		    lineBuffer = buf;
 		}
 		buf[offset++] = (char) c;
 		break;
 	    }
 	}

 	if (offset == 0) {
 	    return null;
 	}

 	char[] ret = new char[offset];
 	System.arraycopy(buf, 0, ret, 0, offset);
 	Arrays.fill(buf, ' ');

 	return ret;
    }
}

Dann Natürlich noch die LoginModule-KLasse:
Java:
package sample.module;

import java.util.*;
import java.io.IOException;
import javax.security.auth.*;
import javax.security.auth.callback.*;
import javax.security.auth.login.*;
import javax.security.auth.spi.*;

import sample.principal.SamplePrincipal;


public class SampleLoginModule implements LoginModule {

    // initial state
    private Subject subject;
    private CallbackHandler callbackHandler;
    private Map sharedState;
    private Map options;

    // configurable option
    private boolean debug = false;

    // the authentication status
    private boolean succeeded = false;
    private boolean commitSucceeded = false;

    // username and password
    private String username;
    private char[] password;

    // testUser's SamplePrincipal
    private SamplePrincipal userPrincipal;


    public void initialize(Subject subject, CallbackHandler callbackHandler,
			Map sharedState, Map options) {
 
	this.subject = subject;
	this.callbackHandler = callbackHandler;
	this.sharedState = sharedState;
	this.options = options;

	// initialize any configured options
	debug = "true".equalsIgnoreCase((String)options.get("debug"));
    }

   
    public boolean login() throws LoginException {

	// prompt for a user name and password
	if (callbackHandler == null)
	    throw new LoginException("Error: no CallbackHandler available " +
			"to garner authentication information from the user");

	Callback[] callbacks = new Callback[2];
	callbacks[0] = new NameCallback("user name: ");
	callbacks[1] = new PasswordCallback("password: ", false);
 
	try {
	    callbackHandler.handle(callbacks);
	    username = ((NameCallback)callbacks[0]).getName();
	    char[] tmpPassword = ((PasswordCallback)callbacks[1]).getPassword();
	    if (tmpPassword == null) {
		// treat a NULL password as an empty password
		tmpPassword = new char[0];
	    }
	    password = new char[tmpPassword.length];
	    System.arraycopy(tmpPassword, 0,
			password, 0, tmpPassword.length);
	    ((PasswordCallback)callbacks[1]).clearPassword();
 
	} catch (java.io.IOException ioe) {
	    throw new LoginException(ioe.toString());
	} catch (UnsupportedCallbackException uce) {
	    throw new LoginException("Error: " + uce.getCallback().toString() +
		" not available to garner authentication information " +
		"from the user");
	}

	// print debugging information
	if (debug) {
	    System.out.println("\t\t[SampleLoginModule] " +
				"user entered user name: " +
				username);
	    System.out.print("\t\t[SampleLoginModule] " +
				"user entered password: ");
	    for (int i = 0; i < password.length; i++)
		System.out.print(password[i]);
	    System.out.println();
	}

	// verify the username/password
	boolean usernameCorrect = false;
	boolean passwordCorrect = false;
	if (username.equals("testUser"))
	    usernameCorrect = true;
	if (usernameCorrect &&
	    password.length == 12 &&
	    password[0] == 't' &&
	    password[1] == 'e' &&
	    password[2] == 's' &&
	    password[3] == 't' &&
	    password[4] == 'P' &&
	    password[5] == 'a' &&
	    password[6] == 's' &&
	    password[7] == 's' &&
	    password[8] == 'w' &&
	    password[9] == 'o' &&
	    password[10] == 'r' &&
	    password[11] == 'd') {

	    // authentication succeeded!!!
	    passwordCorrect = true;
	    if (debug)
		System.out.println("\t\t[SampleLoginModule] " +
				"authentication succeeded");
	    succeeded = true;
	    return true;
	} else {

	    // authentication failed -- clean out state
	    if (debug)
		System.out.println("\t\t[SampleLoginModule] " +
				"authentication failed");
	    succeeded = false;
	    username = null;
	    for (int i = 0; i < password.length; i++)
		password[i] = ' ';
	    password = null;
	    if (!usernameCorrect) {
		throw new FailedLoginException("User Name Incorrect");
	    } else {
		throw new FailedLoginException("Password Incorrect");
	    }
	}
    }


    public boolean commit() throws LoginException {
	if (succeeded == false) {
	    return false;
	} else {
	    // add a Principal (authenticated identity)
	    // to the Subject

	    // assume the user we authenticated is the SamplePrincipal
	    userPrincipal = new SamplePrincipal(username);
	    if (!subject.getPrincipals().contains(userPrincipal))
		subject.getPrincipals().add(userPrincipal);

	    if (debug) {
		System.out.println("\t\t[SampleLoginModule] " +
				"added SamplePrincipal to Subject");
	    }

	    // in any case, clean out state
	    username = null;
	    for (int i = 0; i < password.length; i++)
		password[i] = ' ';
	    password = null;

	    commitSucceeded = true;
	    return true;
	}
    }

  
    public boolean abort() throws LoginException {
	if (succeeded == false) {
	    return false;
	} else if (succeeded == true && commitSucceeded == false) {
	    // login succeeded but overall authentication failed
	    succeeded = false;
	    username = null;
	    if (password != null) {
		for (int i = 0; i < password.length; i++)
		    password[i] = ' ';
		password = null;
	    }
	    userPrincipal = null;
	} else {
	    // overall authentication succeeded and commit succeeded,
	    // but someone else's commit failed
	    logout();
	}
	return true;
    }

  
    public boolean logout() throws LoginException {

	subject.getPrincipals().remove(userPrincipal);
	succeeded = false;
	succeeded = commitSucceeded;
	username = null;
	if (password != null) {
	    for (int i = 0; i < password.length; i++)
		password[i] = ' ';
	    password = null;
	}
	userPrincipal = null;
	return true;
    }
}
und noch die Principal-Klasse:

Java:
package sample.principal;

import java.security.Principal;


public class SamplePrincipal implements Principal, java.io.Serializable {

 
    private String name;


    public SamplePrincipal(String name) {
	if (name == null)
	    throw new NullPointerException("illegal null input");

	this.name = name;
    }


    public String getName() {
	return name;
    }


    public String toString() {
	return("SamplePrincipal:  " + name);
    }


    public boolean equals(Object o) {
	if (o == null)
	    return false;

        if (this == o)
            return true;
 
        if (!(o instanceof SamplePrincipal))
            return false;
        SamplePrincipal that = (SamplePrincipal)o;

	if (this.getName().equals(that.getName()))
	    return true;
	return false;
    }
 
    public int hashCode() {
	return name.hashCode();
    }
}

Und meine Config-Datei sieht wie folgt aus:

Sample {
sample.module.SampleLoginModule required debug=true;
};




Ich kriege es einfach nicht zum laufen und die Fehlermeldung kann ich auch nicht so ganz deuten. Findet er die Config-Datei nicht oder was findet er nicht?

Vielleicht hat einer von euch eine Ahnung?
Das ich mit nem Mac arbeite dürfte wohl nicht von bedeutung sein, oder?

Gruß
BeginJava
 
Zuletzt bearbeitet:

BeginJava

Mitglied
Auch wenn ich jetzt wie ein Idiot darstehe.
- Klasse SampleAcn
-
Java:
 lc = new LoginContext("Sample", new MyCallbackHandler());

Ich dachte gelesen zu haben, dass er die findet, wenn ich den Namen angebe, als "Sample".

Muss ich noch den genauen Pfad irgendwo übergeben?
 

BeginJava

Mitglied
Vielen Dank schonmal!!!
Ja das hast du natürlich recht. Darüber habe ich schlaumeier nicht nachgedacht.

Also Durchgelesen habe ich es :rtfm:

Auch wenn ich mich jetzt Bloßstelle
Aber wie kann ich das auf eclipse übertragen?
Der erste Teil erklärt es ja mit Eingaben über die Console.

Eine Java security properties file finde ich i-wie in eclipse nicht. ???:L
 

BeginJava

Mitglied
Hab´s geschafft, danke :toll:

Lösung des Problems:

Java:
System.setProperty("java.security.auth.login.config", "sample_jaas.config");


Vielen Dank nochmal.
 

hexx

Mitglied
Eclipse:

Unter "Run->Run Configurations" deine Konfiguration auswählen, dann auf dem Reiter "Arguments" unter "VM arguments" eintragen.

Wenn dein Programm ohne SecurityManager in einer nicht restriktiven Umgebung läuft, kannst du die Systemproperty auch einfach im Quellcode setzen:

Java:
System.setProperty( "java.security.auth.login.config", "/path/to/file.conf");

Eine Java security properties file finde ich i-wie in eclipse nicht.

Die hat auch mit Eclipse nichts zu tun, sondern liegt in "lib/security" unter deinem JRE/JDK.

EDIT: Zu spät ;-)
 
Zuletzt bearbeitet:

BeginJava

Mitglied
aber nur ne Sekunde zu spät ;)

Aber wie gesagt, danke für die Hilfe. Daran hätte ich noch stunden gesessen, also :toll:

Jetzt muss ich das Noch irgendwie so bauen, dass ich das NTLoginModule verwende und dann ich bin fast durch. :)



NTLoginModule (Java Authentication and Authorization Service )

Weißt du ob ich dafür mir das com.sun.security.auth package holen muss oder ich einfach eine klasse schreibe Klasse "NTLoginModule", die LoginModule Implementiert?
 

hexx

Mitglied
Wenn du das NTLoginModule verwenden möchtest, musst du nichts selber implementierten. Das ist im JDK/JRE mit dabei. Einfach in deiner JAAS-Konfig Datei anstatt dem SampleLoginModule, das NTLoginModule angeben; das ist alles.
 

BeginJava

Mitglied
Ich habe es gerade ausprobiert und es geht, cool danke.

Kennst du vllt. ein gutes Tutorial für dieses NTLoginModule. Ich will verstehen wie es funktioniert, also mit den Credentials, Principals, Subjects, wo er sich Namen und Passwort her holt usw.

Ich habe da echt zu wenig Plan von
 

hexx

Mitglied
Nein, ein spezielles Tutorial zum NTLoginModule kenne ich nicht. Es gibt aber ein freies Buch zum übergeordnetem Thema: http://www.jaasbook.com/. Das kannst du dir ja mal ansehen, um einen Überblick über das Zusammenarbeiten von Subject, Principal, Credential, usw. zu bekommen.

Das NTLoginModule ist windows-spezifisch. Es authentifiziert den Benutzer nicht selbst; ein angegebener Callbackhandler wird ignoriert. Das Module greift lediglich via JNI auf eine DLL zu, die über die WiN32-API die Informationen des aktuell eingeloggten Benutzers ausliest. Du kannst dir ja mal den Quellcode ansehen:

Login Modules
DLL
 

BeginJava

Mitglied
Cool, danke.

Hab mich da jetzt etwas reingelesen.
Den rest versuche ich alleine zu machen. Mehr zu fragen, traue ich mich nicht. Die fragen die ich stelle sind ja schon fast peinlich :oops:

Aber finde es gut, das man hier nicht gleich angeschnautzt wird, von wegen, kann man alles nachlesen und sowas, sondern einem geholfen wird.


also ein echt gutes Forum
 

BeginJava

Mitglied
Hi,

das NTLoginModule liefert Username, UserSID, usw. und gibt diese aus.
Weiß jemand evtl. wie/ob man die Ausgaben (Importing Info) desaktivieren kann.
 

Neue Themen


Oben