Tuesday, June 30, 2015

Handling logout mechanism in J2EE way

Last time when I was working with Spring, the logout was handled in such a way:
  <http auto-config="true">
    ...

    <logout logout-success-url="/pages/login.xhtml?faces-redirect=true">
  </http>
But now I'm doing it in pure J2EE way, thus this is what I got:
 <h:form>
  <p:commandbutton action="#{myController.logout}" value="logout" />
 </h:form>
@ManagedBean
@RequestScoped
public class MyController {

 ...
 ...
 
 public void logout() throws IOException {
  ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
  ec.invalidateSession();
  ec.redirect(ec.getRequestContextPath() + "/login.xhtml");
 }
}
Notice the huge difference? With Spring, one statement rules the world.

How could I wire j_username and j_password in managed bean?

Two things required in a typical design of an authentication mechanism in J2EE 6; one is the security-constraint in Deployment Descriptor as shown below:
...

 <security-constraint>
  <web-resource-collection>
   <web-resource-name>Authentication</web-resource-name>
   <description>Please login</description>
   <url-pattern>/pages/*</url-pattern>
   <http-method>GET</http-method>
   <http-method>POST</http-method>
  </web-resource-collection>
  <auth-constraint>
   <role-name>Junior</role-name>
  </auth-constraint>
 </security-constraint>

 <login-config>
  <auth-method>FORM</auth-method>
  <form-login-config>
   <form-login-page>/login.xhtml</form-login-page>
   <form-error-page>/error.xhtml</form-error-page>
  </form-login-config>
 </login-config>
 
 <security-role>
  <role-name>Junior</role-name>
 </security-role>
Second would be the form in login page:
...

 <form method="post" action="j_security_check">
  <h:outputLabel value="Username: " />
  <p:inputText id="j_username" />
  <h:outputLabel value="Password: " />
     <p:password id="j_password" />
     <p:commandButton action="#{myController.link}" value="please login"/>
     
 </form>
As in the value shown in url-pattern, I have my protected page sit inside this directory. Whereas the login page doesn't need to be inside that directory, it would be best to put in the root of WebContent. The managed bean that wired the login page is as follow:
@ManagedBean
@RequestScoped
public class MyController {

 public void link() {
   FacesContext.getCurrentInstance().getExternalContext().redirect("landingpage.xhtml");
 }
}
But then I was wondering whether I'm doing the login page correctly as according to the J2EE 6 standard? Assuming I'm wrong, how could I move j_username, and j_password into a managed bean? After some research on this matter, there are two things need to be done in order to meet my objective. First, the form is no longer require to send post method to j_security_check:
...

 <h:form>
     <h:outputLabel value="Username: " />
     <p:inputText id="username" value="#{myController.username}" />
     <h:outputLabel value="Password: " />
     <p:password id="password" value="#{myController.password}" />
     <p:commandButton action="#{myController.link}" value="link"/>
 </h:form>
And the login process was handled in the managed bean as shown below:
@ManagedBean
@RequestScoped
public class MyController {
 private String username;
 private String password;

 public void link() {
  HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
  
  try {
   request.login(username, password);
   
   FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("user", username);
   FacesContext.getCurrentInstance().getExternalContext().redirect("landingpage.xhtml");
  }
  catch( ServletException e ) {
   ...
  }
 }
}
See it? The j_username, and j_password has been replace by the username and password wired inside the managed bean now. And the form is no longer contain any j_ fields.

Sunday, June 21, 2015

No more urgly game loop in Cocos2dx

   while(!done)
   {
      update(); // keep the game content moving
   }
The above code shows the very important mechanic in game development. Without the loop, the game will always static. But in Cocos2d-x framework, things have changed. I don't do this ugly looping anymore, I just need to override the update(float) in the Scene object like this:
class HelloWorld : public cocos2d::Layer
{
public:
   ...
   ...

   virtual bool init();

   void update(float d);
};

void HelloWorld::update(float d)
{
   ...
   ...
}
And then activate it in the init() like this:
bool HelloWorld::init()
{
   ...

   this->scheduleUpdate();

   return true;
}

Saturday, June 20, 2015

Authenticate web application with Active Directory in JBoss EAP 6

This is so embarrassing. In my previous post, I though I have already done the AD configuration, but that was only for management, not the application. There are 2 different story. Assume I have the following AD configuration:
    dn: CN=user1,OU=Users,DC=huahsin68,DC=org
    objectClass: user
    objectClass: organizationalPerson
    objectClass: person
    objectClass: top
    memberOf: CN=Role_1,OU=Groups,OU=Users,DC=huahsin68,DC=org
    sAMAccountName: user1
    ...
     
    dn: CN=Role_1,OU=Groups,OU=Users,DC=huahsin68,DC=org
    objectClass: group
    objectClass: top
    cn: Role_1
    member: CN=user1,OU=Users,DC=huahsin68,DC=org
    name: Role_1
    ...
For web application, there are 2 things need to be done in order to authenticate users through Active Directory (AD) in JBoss. One is deployment descriptor (web.xml) configuration, and the other one is JBoss configuration (either in domain.xml or standalone.xml). In deployment descriptor, the following configuration shows the regular piece in securing a web application:
      <security-constraint>
     <web-resource-collection>
      <web-resource-name>Authentication</web-resource-name>
      <description>Please login</description>
      <url-pattern>/pages/*</url-pattern>
      <http-method>GET</http-method>
      <http-method>POST</http-method>
     </web-resource-collection>
     <auth-constraint>
      <role-name>Role_1</role-name>
      <role-name>Role_2</role-name>
     </auth-constraint>
      </security-constraint>
    
      <login-config>
     <auth-method>FORM</auth-method>
     <form-login-config>
      <form-login-page>/login.xhtml</form-login-page>
      <form-error-page>/error.xhtml</form-error-page>
     </form-login-config>
      </login-config>
     
      <security-role>
     <role-name>Role_1</role-name>
      </security-role>
      <security-role>
     <role-name>Role_2</role-name>
      </security-role>
Next is JBoss configuration. It has been a hard time for me to configure this as I mess up the role configuration causing me keep hitting HTTP 403. This is not fun at all, but at last I managed to find the solution. Configuration below shows how this is done in order to authenticate through AD.
    <security-domain name="ADRealm" cache-type="default">
       <authentication>
          <login-module code="org.jboss.security.auth.spi.LdapExtLoginModule" flag="required">
             <module-option name="java.naming.factory.initial" value="com.sun.jndi.ldap.LdapCtxFactory"/>
             <module-option name="java.naming.security.authentication" value="simple"/>
             <module-option name="java.naming.provider.url" value="ldap://127.0.0.1:10389"/>
             <module-option name="debug" value="true"/>
             <module-option name="bindDN" value="CN=huahsin,OU=Users,DC=huahsin68,DC=org"/>
             <module-option name="bindCredential" value="Abcd1234"/>
             <module-option name="baseCtxDN" value="OU=Users,DC=huahsin68,DC=org"/>
             <module-option name="baseFilter" value="(sAMAccountName={0})"/>
             <module-option name="searchScope" value="SUBTREE_SCOPE"/>
             <module-option name="allowEmptyPasswords" value="false"/>
             <module-option name="roleAttributeIsDN" value="true"/>
             <module-option name="rolesCtxDN" value="OU=Groups,OU=Users,DC=huahsin68,DC=org"/>
             <module-option name="roleFilter" value="(member={1})"/>
             <module-option name="roleAttributeID" value="memberOf"/>
          </login-module>
       </authentication>
    </security-domain>
A new security domain is created under the <subsystem xmlns="urn:jboss:domain:security:1.1">, don't confuse with the management's configuration. There are 2 different entity. Last but not least, remember to link ADRealm which is define in JBoss configuration in jboss-web.xml (as shown in the following code), otherwise the web application would not be able to authenticate though the AD.
   <jboss-web>
      <security-domain>java:/jaas/ADRealm</security-domain>
   </jboss-web>
Some site info, when the role is found in AD, following log could be seen in server log.
    15:21:48,811 DEBUG [org.apache.catalina.realm] (http-localhost/127.0.0.1:8080-2)   Checking roles GenericPrincipal[huahsin68(Role_1,)] 
    15:21:48,811 DEBUG [org.apache.catalina.realm] (http-localhost/127.0.0.1:8080-2) JBWEB000017: User [user1] has role [Role_1]
    15:21:48,811 DEBUG [org.apache.catalina.realm] (http-localhost/127.0.0.1:8080-2) Role found:  Role_1
But if it doesn’t found, following log would be seen in server log:
    11:32:40,401 DEBUG [org.apache.catalina.realm] (http-localhost/127.0.0.1:8080-2)   Checking roles GenericPrincipal[huahsin68()]
    11:32:40,415 DEBUG [org.apache.catalina.realm] (http-localhost/127.0.0.1:8080-2) JBWEB000016: User [user1] does not have role [Role_1]
    11:32:40,415 DEBUG [org.apache.catalina.realm] (http-localhost/127.0.0.1:8080-2) No role found:  Role_1

Wednesday, June 17, 2015

DTD error in web.xml causing connection timeout

I’m having a bad day today. I'm creating a new project from scratch just for some experiment. After I deployed it to the JBoss server, launch the web in web browser and realize that it takes more than a minute to load the page. The page was rendered correctly at last but the weird thing is I got Connection time out error in the server:
12:02:51,967 SEVERE [org.primefaces.config.ConfigContainer] (http-localhost/127.0.0.1:8080-1) Could not load or parse web.xml: java.net.ConnectException: Connection timed out: connect
     at java.net.TwoStacksPlainSocketImpl.socketConnect(Native Method) [rt.jar:1.7.0_79]
     at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339) [rt.jar:1.7.0_79]
     at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200) [rt.jar:1.7.0_79]
     at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182) [rt.jar:1.7.0_79]
     at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) [rt.jar:1.7.0_79]
     at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) [rt.jar:1.7.0_79]
     at java.net.Socket.connect(Socket.java:579) [rt.jar:1.7.0_79]
     at java.net.Socket.connect(Socket.java:528) [rt.jar:1.7.0_79]
     at sun.net.NetworkClient.doConnect(NetworkClient.java:180) [rt.jar:1.7.0_79]
     at sun.net.www.http.HttpClient.openServer(HttpClient.java:432) [rt.jar:1.7.0_79]
     at sun.net.www.http.HttpClient.openServer(HttpClient.java:527) [rt.jar:1.7.0_79]
     at sun.net.www.http.HttpClient.<init>(HttpClient.java:211) [rt.jar:1.7.0_79]
     at sun.net.www.http.HttpClient.New(HttpClient.java:308) [rt.jar:1.7.0_79]
     at sun.net.www.http.HttpClient.New(HttpClient.java:326) [rt.jar:1.7.0_79]
     at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:997) [rt.jar:1.7.0_79]
     at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:933) [rt.jar:1.7.0_79]
     at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:851) [rt.jar:1.7.0_79]
     at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1301) [rt.jar:1.7.0_79]
     at org.apache.xerces.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:986)
     at org.apache.xerces.impl.XMLEntityManager.startEntity(XMLEntityManager.java:897)
     at org.apache.xerces.impl.XMLEntityManager.startDTDEntity(XMLEntityManager.java:864)
     at org.apache.xerces.impl.XMLDTDScannerImpl.setInputSource(XMLDTDScannerImpl.java:241)
     at org.apache.xerces.impl.XMLDocumentScannerImpl$DTDDispatcher.dispatch(XMLDocumentScannerImpl.java:1001)
     at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:324)
     at org.apache.xerces.parsers.XML11Configuration.parse(XML11Configuration.java:845)
     at org.apache.xerces.parsers.XML11Configuration.parse(XML11Configuration.java:768)
     at org.apache.xerces.parsers.XMLParser.parse(XMLParser.java:108)
     at org.apache.xerces.parsers.DOMParser.parse(DOMParser.java:230)
     at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:285)
     at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:121) [rt.jar:1.7.0_79]
     at org.primefaces.config.ConfigContainer.initConfigFromWebXml(ConfigContainer.java:258) [primefaces-5.0.jar:5.0]
     at org.primefaces.config.ConfigContainer.<init>(ConfigContainer.java:84) [primefaces-5.0.jar:5.0]
     at org.primefaces.context.DefaultApplicationContext.<init>(DefaultApplicationContext.java:35) [primefaces-5.0.jar:5.0]
     at org.primefaces.context.DefaultRequestContext.getApplicationContext(DefaultRequestContext.java:227) [primefaces-5.0.jar:5.0]
     at org.primefaces.metadata.ComponentMetadataTransformerListener.processEvent(ComponentMetadataTransformerListener.java:40) [primefaces-5.0.jar:5.0]
     at javax.faces.event.SystemEvent.processListener(SystemEvent.java:106) [jboss-jsf-api_2.1_spec-2.1.28.Final-redhat-1.jar:2.1.28.Final-redhat-1]
     at com.sun.faces.application.ApplicationImpl.processListeners(ApplicationImpl.java:2166) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at com.sun.faces.application.ApplicationImpl.invokeListenersFor(ApplicationImpl.java:2139) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at com.sun.faces.application.ApplicationImpl.publishEvent(ApplicationImpl.java:303) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at com.sun.faces.application.ApplicationImpl.publishEvent(ApplicationImpl.java:247) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at javax.faces.component.UIComponentBase.publishAfterViewEvents(UIComponentBase.java:2203) [jboss-jsf-api_2.1_spec-2.1.28.Final-redhat-1.jar:2.1.28.Final-redhat-1]
     at javax.faces.component.UIComponentBase.doPostAddProcessing(UIComponentBase.java:1885) [jboss-jsf-api_2.1_spec-2.1.28.Final-redhat-1.jar:2.1.28.Final-redhat-1]
     at javax.faces.component.UIComponentBase.setParent(UIComponentBase.java:405) [jboss-jsf-api_2.1_spec-2.1.28.Final-redhat-1.jar:2.1.28.Final-redhat-1]
     at javax.faces.component.UIComponentBase$FacetsMap.put(UIComponentBase.java:2943) [jboss-jsf-api_2.1_spec-2.1.28.Final-redhat-1.jar:2.1.28.Final-redhat-1]
     at javax.faces.component.UIComponentBase$FacetsMap.put(UIComponentBase.java:2903) [jboss-jsf-api_2.1_spec-2.1.28.Final-redhat-1.jar:2.1.28.Final-redhat-1]
     at javax.faces.component.UIViewRoot.getComponentResources(UIViewRoot.java:1749) [jboss-jsf-api_2.1_spec-2.1.28.Final-redhat-1.jar:2.1.28.Final-redhat-1]
     at javax.faces.component.UIViewRoot.addComponentResource(UIViewRoot.java:517) [jboss-jsf-api_2.1_spec-2.1.28.Final-redhat-1.jar:2.1.28.Final-redhat-1]
     at com.sun.faces.application.annotation.ResourceDependencyHandler.pushResourceToRoot(ResourceDependencyHandler.java:126) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at com.sun.faces.application.annotation.ResourceDependencyHandler.apply(ResourceDependencyHandler.java:107) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at com.sun.faces.application.annotation.AnnotationManager.applyAnnotations(AnnotationManager.java:343) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at com.sun.faces.application.annotation.AnnotationManager.applyComponentAnnotations(AnnotationManager.java:245) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at com.sun.faces.application.ApplicationImpl.applyAnnotations(ApplicationImpl.java:1969) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at com.sun.faces.application.ApplicationImpl.createComponentApplyAnnotations(ApplicationImpl.java:1919) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at com.sun.faces.application.ApplicationImpl.createComponent(ApplicationImpl.java:1163) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.createComponent(ComponentTagHandlerDelegateImpl.java:501) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:169) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120) [jboss-jsf-api_2.1_spec-2.1.28.Final-redhat-1.jar:2.1.28.Final-redhat-1]
     at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:95) [jboss-jsf-api_2.1_spec-2.1.28.Final-redhat-1.jar:2.1.28.Final-redhat-1]
     at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:137) [jboss-jsf-api_2.1_spec-2.1.28.Final-redhat-1.jar:2.1.28.Final-redhat-1]
     at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:187) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120) [jboss-jsf-api_2.1_spec-2.1.28.Final-redhat-1.jar:2.1.28.Final-redhat-1]
     at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:137) [jboss-jsf-api_2.1_spec-2.1.28.Final-redhat-1.jar:2.1.28.Final-redhat-1]
     at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:187) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120) [jboss-jsf-api_2.1_spec-2.1.28.Final-redhat-1.jar:2.1.28.Final-redhat-1]
     at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:95) [jboss-jsf-api_2.1_spec-2.1.28.Final-redhat-1.jar:2.1.28.Final-redhat-1]
     at com.sun.faces.facelets.compiler.NamespaceHandler.apply(NamespaceHandler.java:93) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at com.sun.faces.facelets.compiler.EncodingHandler.apply(EncodingHandler.java:87) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at com.sun.faces.facelets.impl.DefaultFacelet.apply(DefaultFacelet.java:164) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at com.sun.faces.application.view.FaceletViewHandlingStrategy.buildView(FaceletViewHandlingStrategy.java:914) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:99) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139) [jsf-impl-2.1.28.redhat-7.jar:2.1.28.redhat-7]
     at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594) [jboss-jsf-api_2.1_spec-2.1.28.Final-redhat-1.jar:2.1.28.Final-redhat-1]
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:295) [jbossweb-7.4.10.Final-redhat-1.jar:7.4.10.Final-redhat-1]
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214) [jbossweb-7.4.10.Final-redhat-1.jar:7.4.10.Final-redhat-1]
     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:231) [jbossweb-7.4.10.Final-redhat-1.jar:7.4.10.Final-redhat-1]
     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:149) [jbossweb-7.4.10.Final-redhat-1.jar:7.4.10.Final-redhat-1]
     at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:169) [jboss-as-web-7.4.3.Final-redhat-2.jar:7.4.3.Final-redhat-2]
     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:145) [jbossweb-7.4.10.Final-redhat-1.jar:7.4.10.Final-redhat-1]
     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:97) [jbossweb-7.4.10.Final-redhat-1.jar:7.4.10.Final-redhat-1]
     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:102) [jbossweb-7.4.10.Final-redhat-1.jar:7.4.10.Final-redhat-1]
     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) [jbossweb-7.4.10.Final-redhat-1.jar:7.4.10.Final-redhat-1]
     at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856) [jbossweb-7.4.10.Final-redhat-1.jar:7.4.10.Final-redhat-1]
     at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:653) [jbossweb-7.4.10.Final-redhat-1.jar:7.4.10.Final-redhat-1]
     at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:926) [jbossweb-7.4.10.Final-redhat-1.jar:7.4.10.Final-redhat-1]
     at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_79]
I thought this was cause by the JBoss server, then later I found out it was actually cause by the DTD in web.xml. This is what the piece looks like:
    
    <!DOCTYPE web-app PUBLIC
     "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
     "http://java.sun.com/dtd/web-app_2_3.dtd">
    <web-app>
       ... 
    </web-app>
This seems not right as I'm using servlet 3.0, but why does it shows 2.3? When I remove it and restart the server, everything were just fine. Somehow it is not recommended to leave it empty. As I reference to this article, it would be best to put the piece below for Servlet 3.
<web-app id="WebApp_ID" version="3.0"
     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">
       ... 
</web-app>

Monday, June 15, 2015

Authenticate JBoss EAP 6 through Active Directory

The codes shown below represent a portion of the JBoss EAP 6 authentication mechanism in standalone.xml. Notice the user’s authentication details are store in the properties file whenever a user is added through add-user script provided by JBoss. There are 2 properties files, one for user, and one for role.
    <management>
            <security-realms>
                <security-realm name="ManagementRealm">
                    <authentication>
                        <local default-user="$local" skip-group-loading="true"/>
                        <properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/>
                    </authentication>
                    <authorization map-groups-to-roles="false">
                        <properties path="mgmt-groups.properties" relative-to="jboss.server.config.dir"/>
                    </authorization>
                </security-realm>
                ...
                ...
            </security-realms>
            <management-interfaces>
                <native-interface security-realm="ManagementRealm">
                    <socket-binding native="management-native"/>
                </native-interface>
                <http-interface security-realm=" ManagementRealm ">
                    <socket-binding http="management-http"/>
                </http-interface>
            </management-interfaces>
    </management>
My objective is to implement Active Directory (AD) authentication on JBoss, so that it doesn't use the local user (the one that store in the properties file). And the connection established to AD must be secured. First I initiate a connection to AD as defined in <outbound-connections>:
    <management>
        <security-realms>
            ...
        </security-realms>
        <outbound-connections>
            <ldap name="ad" url="ldaps://192.168.1.88:686" search-dn="CN=huahsin,OU=Users, DC=huahsin68,DC=org" search-credential="Abcd1234"/>
        </outbound-connections>
        ...
        ...
    </management>
And then add a new realm, named ADRealm, under the security realm section to search for users. This section is to tells how the searching criteria would be. In my case, I'm using sAMAccountName as the search key, and recursively search starting from Users subtree:
    <security-realms>
        ...
        <security-realm name="ADRealm">
            <authentication>
                <ldap connection="ad" base-dn="OU=Users,DC=huahsin68,DC=org" recursive="true">
                    <username-filter attribute="sAMAccountName"/>
                </ldap>
             </authentication>
        </security-realm>
    <security-realms>
And then I would have to redirect the authentication to use ADRealm rather than ManagementRealm under the <management-interfaces>.
    <management-interfaces>
        <native-interface security-realm="ManagementRealm">
            <socket-binding native="management-native"/>
        </native-interface>
        <http-interface security-realm="ADRealm">
            <socket-binding http="management-http"/>
        </http-interface>
    </management-interfaces>
Now comes to second stage would be to configure SSL so that the JBoss would be able to authentication through a secure channel. Execute the following command to import the certificate into JDK which has been bound to JBoss.

keytool –import –trustkey –file /path/to/adcert.cer –alias ADCert –keystore C:\Tool\jdk1.7.0_79\jre\lib\security\cacerts

Once done! JBoss will now integrate with AD authentication.

Tuesday, June 9, 2015

JSF2 navigation ruin my mood

Hohoho~ I'm just having some fun with JSF2 navigation, it was a real interesting thing. Not at all! Say I have the source page, that could allow me navigate to the target page. Somehow the page doesn't navigate and I were so frustrate what I have been done? In a regular programming practice in JSF2, this is what I have done on the front end site:
<h:body>
 <h:form>
  <p:commandButton action="#{messageListController.link}" value="link">
  </p:commandButton>
 </h:form>
</h:body>
And the messageListController bean will take up the responsibility on the navigation task:
@ManagedBean
@RequestScoped
public class MessageListController {
 public String link() throws IOException {
  
  return "messagePost.html?faces-redirect=true";
 }
}
Guess what will happen? The target page, which is messagePost, will never show. This is because I was mistakenly making messagePost.html instead of messagePost.xhtml. This is what ruin my mood at the end of the day. But fortunately, I have discovered an alternate way to navigate a page. On the front end, I use actionListener like this:
<h:body>
 <h:form>
  <p:commandButton actionListener="#{messageListController.link}" value="link">
  </p:commandButton>
 </h:form>
</h:body>
Then on managed bean site, I would have this:
@ManagedBean
@RequestScoped
public class MessageListController {
 public void link(ActionEvent event) throws IOException {
   FacesContext.getCurrentInstance().getExternalContext().redirect("messagePost.html?faces-redirect=true");
 }
}
Tada! This will still achieve the same result. Thanks to my mistake pushing me to the max power to try every effort I could do.