我试图在服务器负载上调用安全的EJB方法但我得到例外:
09:49:58,011 ERROR [org.jboss.as.ejb3.invocation] (ServerService Thread Pool -- 54) JBAS014134: EJB Invocation failed on component SecuredEJB for method public java.lang.String org.jboss.as.quickstarts.ejb_security.SecuredEJB.getSecurityInfo(): javax.ejb.EJBAccessException: JBAS014502: Invocation on method: public java.lang.String org.jboss.as.quickstarts.ejb_security.SecuredEJB.getSecurityInfo() of bean: SecuredEJB is not allowed
at org.jboss.as.ejb3.security.AuthorizationInterceptor.processInvocation(AuthorizationInterceptor.java:114) [jboss-as-ejb3-7.5.0.Final-redhat-21.jar:7.5.0.Final-redhat-21]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.2.Final-redhat-1.jar:1.1.2.Final-redhat-1]
at org.jboss.as.ejb3.security.SecurityContextInterceptor.processInvocation(SecurityContextInterceptor.java:86) [jboss-as-ejb3-7.5.0.Final-redhat-21.jar:7.5.0.Final-redhat-21]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.2.Final-redhat-1.jar:1.1.2.Final-redhat-1]
at org.jboss.as.ejb3.component.interceptors.ShutDownInterceptorFactory$1.processInvocation(ShutDownInterceptorFactory.java:64) [jboss-as-ejb3-7.5.0.Final-redhat-21.jar:7.5.0.Final-redhat-21]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.2.Final-redhat-1.jar:1.1.2.Final-redhat-1]
at org.jboss.as.ejb3.component.interceptors.LoggingInterceptor.processInvocation(LoggingInterceptor.java:59) [jboss-as-ejb3-7.5.0.Final-redhat-21.jar:7.5.0.Final-redhat-21]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.2.Final-redhat-1.jar:1.1.2.Final-redhat-1]
at org.jboss.as.ee.component.NamespaceContextInterceptor.processInvocation(NamespaceContextInterceptor.java:50) [jboss-as-ee-7.5.0.Final-redhat-21.jar:7.5.0.Final-redhat-21]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.2.Final-redhat-1.jar:1.1.2.Final-redhat-1]
at org.jboss.as.ejb3.component.interceptors.AdditionalSetupInterceptor.processInvocation(AdditionalSetupInterceptor.java:55) [jboss-as-ejb3-7.5.0.Final-redhat-21.jar:7.5.0.Final-redhat-21]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.2.Final-redhat-1.jar:1.1.2.Final-redhat-1]
at org.jboss.as.ee.component.TCCLInterceptor.processInvocation(TCCLInterceptor.java:45) [jboss-as-ee-7.5.0.Final-redhat-21.jar:7.5.0.Final-redhat-21]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.2.Final-redhat-1.jar:1.1.2.Final-redhat-1]
at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61) [jboss-invocation-1.1.2.Final-redhat-1.jar:1.1.2.Final-redhat-1]
at org.jboss.as.ee.component.ViewService$View.invoke(ViewService.java:185) [jboss-as-ee-7.5.0.Final-redhat-21.jar:7.5.0.Final-redhat-21]
at org.jboss.as.ee.component.ViewDescription$1.processInvocation(ViewDescription.java:185) [jboss-as-ee-7.5.0.Final-redhat-21.jar:7.5.0.Final-redhat-21]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.2.Final-redhat-1.jar:1.1.2.Final-redhat-1]
at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61) [jboss-invocation-1.1.2.Final-redhat-1.jar:1.1.2.Final-redhat-1]
at org.jboss.as.ee.component.ProxyInvocationHandler.invoke(ProxyInvocationHandler.java:73) [jboss-as-ee-7.5.0.Final-redhat-21.jar:7.5.0.Final-redhat-21]
at org.jboss.as.quickstarts.ejb_security.SecuredEJB$$$view1.getSecurityInfo(Unknown Source) [classes:]
at org.jboss.as.quickstarts.ejb_security.SecuredEJBServlet.init(SecuredEJBServlet.java:55) [classes:]
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1194) [jbossweb-7.5.7.Final-redhat-1.jar:7.5.7.Final-redhat-1]
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1100) [jbossweb-7.5.7.Final-redhat-1.jar:7.5.7.Final-redhat-1]
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:3593) [jbossweb-7.5.7.Final-redhat-1.jar:7.5.7.Final-redhat-1]
at org.apache.catalina.core.StandardContext.start(StandardContext.java:3802) [jbossweb-7.5.7.Final-redhat-1.jar:7.5.7.Final-redhat-1]
at org.jboss.as.web.deployment.WebDeploymentService.doStart(WebDeploymentService.java:163) [jboss-as-web-7.5.0.Final-redhat-21.jar:7.5.0.Final-redhat-21]
at org.jboss.as.web.deployment.WebDeploymentService.access$000(WebDeploymentService.java:61) [jboss-as-web-7.5.0.Final-redhat-21.jar:7.5.0.Final-redhat-21]
at org.jboss.as.web.deployment.WebDeploymentService$1.run(WebDeploymentService.java:96) [jboss-as-web-7.5.0.Final-redhat-21.jar:7.5.0.Final-redhat-21]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [rt.jar:1.7.0_55]
at java.util.concurrent.FutureTask.run(FutureTask.java:262) [rt.jar:1.7.0_55]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_55]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_55]
at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_55]
at org.jboss.threads.JBossThread.run(JBossThread.java:122) [jboss-threads-2.1.2.Final-redhat-1.jar:2.1.2.Final-redhat-1]
我的项目结构是:
SecuredEJBServlet.java
@SuppressWarnings("serial")
@WebServlet("/SecuredEJBServlet")
@ServletSecurity(@HttpConstraint(rolesAllowed = "quickstarts"))
public class SecuredEJBServlet extends HttpServlet {
@EJB
private SecuredEJB securedEJB;
@Override
public void init(javax.servlet.ServletConfig arg0) throws javax.servlet.ServletException{
Subject s = CMnJAASLogin.loginMethod();
runAs(s);
super.init(arg0);
System.out.println("Inside init...");
securedEJB.getName();
//securedEJB.getSecurityInfo();
}
private void runAs(Subject s){
Subject.doAs(s, new PrivilegedAction<Object>() {
@Override
public Object run() {
System.out.println("Inside privileged action");
securedEJB.getSecurityInfo();
return null;
}
});
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
securedEJB.getName();
String principal = securedEJB.getSecurityInfo();
...
}
SecuredEJB.java
@Stateless
@DeclareRoles("java")
@SecurityDomain("custom")
public class SecuredEJB {
@Resource
private SessionContext ctx;
@RolesAllowed({ "java" })
public String getSecurityInfo() {
Principal principal = ctx.getCallerPrincipal();
return principal.toString();
}
@PermitAll
public void getName(){
System.out.println(principal.getName());
}
}
CMnAuthenticator.java
public class CMnAuthenticator extends UsernamePasswordLoginModule{
@Override
protected String getUsersPassword() throws LoginException {
return "java";
}
@Override
protected boolean validatePassword(String passwordWant, String passwordHave){
return true;
}
@Override
protected Group[] getRoleSets() throws LoginException {
HashMap setsMap = new HashMap();
String groupName = "Roles";
Group group = (Group) setsMap.get(groupName);
if (group == null) {
group = new SimpleGroup(groupName);
setsMap.put(groupName, group);
}
try {
Principal p = super.createIdentity("quickstarts");
group.addMember(p);
}
catch (Exception e) {
e.printStackTrace();
}
Group[] roleSets = new Group[setsMap.size()];
setsMap.values().toArray(roleSets);
return roleSets;
}
}
CMnEJBAuthenticator.java
public class CMnEJBAuthenticator extends UsernamePasswordLoginModule {
@Override
protected String getUsersPassword() throws LoginException {
return "java";
}
@Override
protected boolean validatePassword(String passwordWant, String passwordHave){
return true;
}
@Override
protected Group[] getRoleSets() throws LoginException {
System.out.println("Inside CMnEJBAuthenticator:getRoleSets...");
HashMap setsMap = new HashMap();
String groupName = "Roles";
Group group = (Group) setsMap.get(groupName);
if (group == null) {
group = new SimpleGroup(groupName);
setsMap.put(groupName, group);
}
try {
Principal p = super.createIdentity("java");
group.addMember(p);
}
catch (Exception e) {
e.printStackTrace();
}
Group[] roleSets = new Group[setsMap.size()];
setsMap.values().toArray(roleSets);
return roleSets;
}
}
的JBoss-web.xml中
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss-web>
<jboss-web xmlns="http://www.jboss.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jboss.org/schema/jbossas
http://www.jboss.org/schema/jbossas/jboss-web_7_2.xsd">
<!-- Configure usage of the security domain "other" -->
<security-domain>servlet-security-quickstart</security-domain>
<disable-audit>true</disable-audit>
</jboss-web>
的web.xml
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!-- Configure login to be HTTP Basic -->
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>RealmUsersRoles</realm-name>
</login-config>
<servlet>
<servlet-name>bootstrap</servlet-name>
<servlet-class>org.jboss.as.quickstarts.ejb_security.SecuredEJBServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>bootstrap</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
standalone.xml
<security-domain name="custom" cache-type="default">
<authentication>
<login-module code="org.jboss.as.quickstarts.ejb_security.others.CMnEJBAuthenticator" flag="required">
<module-option name="unauthenticatedIdentity" value="Super"/>
</login-module>
</authentication>
</security-domain>
<security-domain name="servlet-security-quickstart" cache-type="default">
<authentication>
<login-module code="org.jboss.as.quickstarts.ejb_security.others.CMnAuthenticator" flag="required">
<module-option name="unauthenticatedIdentity" value="Super"/>
</login-module>
</authentication>
</security-domain>
Jaas身份验证:
package org.jboss.as.quickstarts.ejb_security.others;
import javax.security.auth.Subject;
import javax.security.auth.callback.*;
import javax.security.auth.login.LoginContext;
import java.io.IOException;
public class CMnJAASLogin {
public static Subject loginMethod(){
LoginContext lc = null;
CallbackHandler cabHndlr = new CallbackHandler() {
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof NameCallback) {
NameCallback nc = (NameCallback) callbacks[i];
nc.setName("java");
} else if (callbacks[i] instanceof PasswordCallback) {
PasswordCallback pc = (PasswordCallback) callbacks[i];
pc.setPassword("java".toCharArray());
} else {
throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
}
}
}
};
try {
lc = new LoginContext("custom", cabHndlr);
lc.login();
return lc.getSubject();
}catch(Exception ex){
ex.printStackTrace();
}
return null;
}
}
知道我缺少什么吗?
注意:我正在研究JBoss EAP 6.4和java 1.7
将@RunAs(“java”)添加到Servlet类可以解决这个直接问题。
但是,如果我需要拒绝其他用户访问,RunAs注释将无法帮助那里。
所以,我需要以这种方式解决它(如果没有用户调用方法/ ejb / servlet,请使用“java”,否则使用该用户的角色。
答案 0 :(得分:0)
我没有尝试过这个,但是servlet规范的§15.3.1说你只需要在web.xml中为你的servlet定义添加一个run-as
元素:
<servlet>
<servlet-name>bootstrap</servlet-name>
<servlet-class>org.jboss.as.quickstarts.ejb_security.SecuredEJBServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<run-as>java</run-as>
</servlet>
但是,对于正常认证的servlet调用,是否将实际经过身份验证的主体传播到EJB并不完全清楚。你将不得不尝试看看。
答案 1 :(得分:0)
我在AppConfigurationProperty中使用org.jboss.security.ClientLoginModule后解决了这个问题。
最后,JAAS类看起来像这样:
import javax.security.auth.Subject;
import javax.security.auth.callback.*;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class CMnJAASLogin {
public static LoginContext loginMethod() {
LoginContext lc = null;
CallbackHandler cabHndlr = new CallbackHandler() {
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof NameCallback) {
NameCallback nc = (NameCallback) callbacks[i];
nc.setName("java");
} else if (callbacks[i] instanceof PasswordCallback) {
PasswordCallback pc = (PasswordCallback) callbacks[i];
pc.setPassword("java".toCharArray());
} else {
throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
}
}
}
};
try {
String configurationName = "JBoss Test";
Configuration config = new JBossJaasConfiguration(configurationName);
lc = new LoginContext(configurationName, new Subject(), cabHndlr, config);
return lc;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
static class JBossJaasConfiguration extends Configuration {
private final String configurationName;
JBossJaasConfiguration(String configurationName) {
this.configurationName = configurationName;
}
@Override
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
if (!configurationName.equals(name)) {
throw new IllegalArgumentException("Unexpected configuration name '" + name + "'");
}
return new AppConfigurationEntry[]{
createClientLoginModuleConfigEntry(),
};
}
private AppConfigurationEntry createClientLoginModuleConfigEntry() {
Map<String, String> options = new HashMap<String, String>();
options.put("multi-threaded", "true");
options.put("restore-login-identity", "true");
return new AppConfigurationEntry("org.jboss.security.ClientLoginModule",
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
}
}
}
整个项目上传到:https://github.com/shekharswaraj/EJBSecurity
注意:它只是一个包含许多硬编码值的测试项目。整个项目已在EAP6.4快速入门的ejb-security项目之上进行了修改。