Java认证和授权服务 JAAS 之 授权

前提

请先看,JAAS 认证部分: http://blog.csdn.net/conquer0715/article/details/78204889


配置文件和源码

jaas.config
/** 登录配置 **/
Sample {
   jaas.MyLoginModule required debug=true;
};

jaas.policy
grant codeBase "file:/home/conquer/mine/work_space/idea/Eden/jse/target/classes/*" {
        //permission java.security.AllPermission;

        permission javax.security.auth.AuthPermission "createLoginContext.Sample";
        permission javax.security.auth.AuthPermission "modifyPrincipals";
        permission javax.security.auth.AuthPermission "doAsPrivileged";
};

// JAAS 授权,授权给指定的用户或身份
grant codeBase "file:/home/conquer/mine/work_space/idea/Eden/jse/target/classes/*",
        Principal jaas.SamplePrincipal "user" {

   permission java.util.PropertyPermission "java.home", "read";
   permission java.util.PropertyPermission "user.home", "read";
   permission java.io.FilePermission "foo.txt", "read";
};
MyLoginModule.java

package jaas;

import javax.security.auth.Subject;
import javax.security.auth.callback.*;
import javax.security.auth.login.FailedLoginException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import java.security.Principal;
import java.util.Map;

public class MyLoginModule implements LoginModule {

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

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

    // user's Principal
    private Principal userPrincipal;


    // initial state
    private Subject subject;
    private CallbackHandler callbackHandler;


    /**
     * Initialize this <code>LoginModule</code>.
     */
    public void initialize(Subject subject,
                           CallbackHandler callbackHandler,
                           Map<java.lang.String, ?> sharedState,
                           Map<java.lang.String, ?> options) {

        this.subject = subject;
        this.callbackHandler = callbackHandler;
    }

    /**
     * Authenticate the user by prompting for a user name and password.
     */
    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[4];
        callbacks[0] = new NameCallback("user name");
        callbacks[1] = new PasswordCallback("password", false);
        callbacks[2] = new TextOutputCallback(TextOutputCallback.INFORMATION, "hello, just a msg!");
        callbacks[3] = new TextOutputCallback(TextOutputCallback.WARNING, "just warn you!");

        try {
            callbackHandler.handle(callbacks);
            NameCallback nameCallback = (NameCallback) callbacks[0];
            PasswordCallback passwordCallback = (PasswordCallback) callbacks[1];

            username = nameCallback.getName();

            char[] tmpPassword = passwordCallback.getPassword();
            passwordCallback.clearPassword();// clean password in memory space
            if (tmpPassword == null) {
                tmpPassword = new char[0];// treat a NULL password as an empty password
            }
            password = new char[tmpPassword.length];
            System.arraycopy(tmpPassword, 0, password, 0, tmpPassword.length);
        } catch (Exception e) {
            e.printStackTrace();
        }


        // verify the username/password
        boolean usernameCorrect = false;
        if (username.equals("user")) usernameCorrect = true;

        if (usernameCorrect &&
                password.length == 3 &&
                password[0] == 'p' &&
                password[1] == 'w' &&
                password[2] == 'd') {

            userPwdSucceeded = true;
        } else {
            userPwdSucceeded = false;
            cleanUserAndPwdData();
            if (!usernameCorrect) {
                throw new FailedLoginException("User Name Incorrect");
            } else {
                throw new FailedLoginException("Password Incorrect");
            }
        }
        return userPwdSucceeded;
    }

    public boolean commit() throws LoginException {
        if (!userPwdSucceeded) return false;

        // add a Principal (authenticated identity) to the Subject
        userPrincipal = new SamplePrincipal(username);
        subject.getPrincipals().add(userPrincipal);

        // in any case, clean out state
        cleanUserAndPwdData();

        return commitSucceeded = true;
    }

    public boolean abort() throws LoginException {
        if (!userPwdSucceeded) return false;

        if (commitSucceeded) {
            logout();
        } else {
            cleanState();
        }

        return true;
    }

    public boolean logout() throws LoginException {
        subject.getPrincipals().remove(userPrincipal);
        cleanState();
        userPwdSucceeded = commitSucceeded;
        return true;
    }

    private void cleanState() {
        userPwdSucceeded = false;
        cleanUserAndPwdData();
        userPrincipal = null;
    }

    private void cleanUserAndPwdData() {
        username = null;
        if (password != null) {
            for (int i = 0; i < password.length; i++)
                password[i] = ' ';
            password = null;
        }
    }
}

MyCallbackHandler.java
package jaas;

import javax.security.auth.callback.*;
import java.io.IOException;

public class MyCallbackHandler implements CallbackHandler {

    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.err.println("ERROR: " + toc.getMessage());
                        break;
                    case TextOutputCallback.WARNING:
                        System.err.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];
                String name = "user";// TODO 这里可以实现为从控制台允许用户输入等方式接收用户参数。。。
                nc.setName(name);
            } else if (callbacks[i] instanceof PasswordCallback) {// prompt the user for sensitive information
                PasswordCallback pc = (PasswordCallback) callbacks[i];
                String pwd = "pwd";// TODO 这里可以实现为从控制台允许用户输入等方式接收用户参数。。。
                pc.setPassword(pwd.toCharArray());
            } else {
                throw new UnsupportedCallbackException
                        (callbacks[i], "Unrecognized Callback");
            }
        }
    }
}
SamplePrincipal.java
package jaas;

import java.security.Principal;

public class SamplePrincipal implements Principal {
    private String name;

    public SamplePrincipal(String name) {
        this.name = name;
    }

    public String getName() {
        return 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();
    }
}

MyPrivilegedAction.java
package jaas;

import java.io.File;
import java.security.PrivilegedAction;

public class MyPrivilegedAction implements PrivilegedAction {

    public Object run() {

        System.out.println("\nYour java.home property value is: "
                + System.getProperty("java.home"));

        System.out.println("\nYour user.home property value is: "
                + System.getProperty("user.home"));

        File f = new File("foo.txt");
        System.out.print("\nfoo.txt does ");
        if (!f.exists())
            System.out.print("not ");
        System.out.println("exist in the current working directory.");
        return null;
    }
}

测试代码:
package jaas;

import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import java.security.Principal;
import java.security.PrivilegedAction;

public class Main {
    public static void main(String[] args) throws LoginException {
        // 配置文件中查找 Sample 名字的 LoginModule,并指定 CallbackHandler
        LoginContext lc = new LoginContext("Sample", new MyCallbackHandler());

        try {
            lc.login();
            Subject subject = lc.getSubject();
//            System.out.println(subject);
            System.out.println("Authentication succeeded!");


            // 下面是 JAAS “授权” 示例代码
            Subject mySubject = lc.getSubject();
            System.out.println("Authenticated user has the following Principals:");
            for (Principal principal : mySubject.getPrincipals()) {
                System.out.println("\t" + principal.toString());
            }

            System.out.println("User has " +
                    mySubject.getPublicCredentials().size() +
                    " Public Credential(s)");

            // now try to execute the MyPrivilegedAction as the authenticated Subject
            PrivilegedAction action = new MyPrivilegedAction();
            Subject.doAsPrivileged(mySubject, action, null);

        } catch (LoginException e) {
            System.err.println("Authentication failed:" + e.getMessage());
            e.printStackTrace();
        }
    }
}

说明

其它类的说明请看 JAAS 认证部分: http://blog.csdn.net/conquer0715/article/details/78204889 文章, 
MyPrivilegedAction:是我们需要验证权限的类,它实现了 java.security.PrivilegedAction 安全接口。
javax.security.auth.Subject#getPrincipals()方法可以获取到当前登录模块内所有已经成功验证的身份。
javax.security.auth.Subject#getPublicCredentials()方法可以获取到当前的所有证书。

运行代码,修改 policy 权限文件可以发现,只有经过授权的用户才可以运行MyPrivilegedAction里面的代码。

发布了147 篇原创文章 · 获赞 66 · 访问量 95万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览