我跟着this tutorial学习了JAAS。这个例子对我有用,所以我创建了自己的版本(我使用的是Tomcat 6和Java 6),但我无法让它工作(帖子底部的例外)。
(因为代理,我不能把这些来源放在ZIP中。抱歉。)
这是JAAS:
TestJAAS {
test.auth.MyModule required debug=true;
};
这是用户Principal
:
public class MyUser implements Principal {
private String name;
public MyUser(String name) {
super();
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
这是角色Principal
:
public final class MyRole implements Principal {
public String getName() {
return "Superman";
}
}
这是登录模块:
public class MyModule implements LoginModule {
private CallbackHandler handler;
private Subject subject;
private MyUser user;
private final MyRole ROLE = new MyRole();
@Override
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map<String, ?> sharedState, Map<String, ?> options) {
this.handler = callbackHandler;
this.subject = subject;
}
public boolean login() throws LoginException {
NameCallback nc = new NameCallback("login");
PasswordCallback pc = new PasswordCallback("password", false);
String name = nc.getName();
String pass = String.valueOf(pc.getPassword());
try {
handler.handle(new Callback[]{nc, pc});
} catch (Exception ex) {
throw new LoginException(ex.getMessage());
}
if ("123".equals(name) && "secret".equals(pass)) {
user = new MyUser(name);
return true;
}
throw new LoginException();
}
public boolean commit() throws LoginException {
subject.getPrincipals().add(user);
subject.getPrincipals().add(ROLE);
return true;
}
public boolean abort() throws LoginException {
return false;
}
public boolean logout() throws LoginException {
subject.getPrincipals().remove(user);
subject.getPrincipals().remove(ROLE);
return true;
}
}
这是context.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Realm className="org.apache.catalina.realm.JAASRealm" appName="TestJAAS"
userClassNames="test.auth.MyUser" roleClassNames="test.auth.MyRole" />
</Context>
这是web.xml
:
<security-constraint>
<web-resource-collection>
<web-resource-name>MyProtectedResources</web-resource-name>
<url-pattern>/admin/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>Superman</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>Superman</role-name>
</security-role>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>MyProtectedResources</realm-name>
</login-config>
当我尝试登录http://localhost:8080/TestJAAS/admin/admin.html
时,这是个例外:
5-dic-2013 10.07.29 org.apache.catalina.realm.JAASRealm authenticate
AVVERTENZA: Login exception authenticating username "123"
javax.security.auth.login.LoginException: java.lang.NullPointerException
at java.lang.String.<init>(String.java:177)
at java.lang.String.valueOf(String.java:2840)
at test.auth.MyModule.login(MyModule.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:769)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:186)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:683)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
at javax.security.auth.login.LoginContext.login(LoginContext.java:579)
at org.apache.catalina.realm.JAASRealm.authenticate(JAASRealm.java:409)
at org.apache.catalina.realm.JAASRealm.authenticate(JAASRealm.java:334)
at org.apache.catalina.authenticator.BasicAuthenticator.authenticate(BasicAuthenticator.java:181)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:528)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:662)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:872)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:186)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:683)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
at javax.security.auth.login.LoginContext.login(LoginContext.java:579)
at org.apache.catalina.realm.JAASRealm.authenticate(JAASRealm.java:409)
at org.apache.catalina.realm.JAASRealm.authenticate(JAASRealm.java:334)
at org.apache.catalina.authenticator.BasicAuthenticator.authenticate(BasicAuthenticator.java:181)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:528)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:662)
正确加载配置文件。为什么我的用户名和密码是null
?提前谢谢。
答案 0 :(得分:2)
此代码中至少有一个错误:
String name = nc.getName();
String pass = String.valueOf(pc.getPassword());
try {
handler.handle(new Callback[]{nc, pc});
} catch (Exception ex) {
throw new LoginException(ex.getMessage());
}
在回调处理程序填充之前,您从回调中读取了名称/密码!!!
您需要将String name=...;String pass=...
部分放在 handler.handle(...)
之后。您链接的示例也是这样做的。