HttpAuthenticationMechanism allow customize your own HTTP authentication mechanism.
An examples for custom HttpAuthenticationMechanism.
@ApplicationScopedpublicclassTestAuthenticationMechanismimplementsHttpAuthenticationMechanism { @InjectprivateIdentityStoreHandler identityStoreHandler; @OverridepublicAuthenticationStatusvalidateRequest(HttpServletRequest request,HttpServletResponse response,HttpMessageContext httpMessageContext) throwsAuthenticationException {finalString name =request.getParameter("name");finalString pwd =request.getParameter("password");if (name !=null&& pwd !=null ) {// Get the (caller) name and password from the request// NOTE: This is for the smallest possible example only. In practice// putting the password in a request query parameter is highly// insecurePassword password =newPassword(pwd);// Delegate the {credentials in -> identity data out} function to// the Identity StoreCredentialValidationResult result =identityStoreHandler.validate(newUsernamePasswordCredential(name, password));if (result.getStatus() == VALID) {// Communicate the details of the authenticated user to the// container. In many cases the underlying handler will just store the details // and the container will actually handle the login after we return from // this method.returnhttpMessageContext.notifyContainerAboutLogin(result.getCallerPrincipal(),result.getCallerGroups()); }returnhttpMessageContext.responseUnauthorized(); }returnhttpMessageContext.doNothing(); }}
validate of IdentityStoreHandler will transport the validation to an application scoped IdentityStore or container built-in approach to handle it.
Java EE Security API provides three built-in annotations('@BasicAuthenticationMechanismDefinition', 'FormAuthenticationMechanismDefinition', '@CustomFormAuthenticationMechanismDefinition') to handle HTTP Basic, Form, a custom form authentication.
An example of '@BasicAuthenticationMechanismDefinition'.
@BasicAuthenticationMechanismDefinition( realmName="${'test realm'}"// Doesn't need to be expression, just for example)@WebServlet("/servlet")@DeclareRoles({ "foo","bar","kaz"})@ServletSecurity(@HttpConstraint(rolesAllowed ="foo"))publicclassTestServletextendsHttpServlet {privatestaticfinallong serialVersionUID =1L; @OverridepublicvoiddoGet(HttpServletRequest request,HttpServletResponse response) throwsServletException,IOException {response.getWriter().write("This is a servlet \n");String webName =null;if (request.getUserPrincipal() !=null) { webName =request.getUserPrincipal().getName(); }response.getWriter().write("web username: "+ webName +"\n");response.getWriter().write("web user has role \"foo\": "+request.isUserInRole("foo") +"\n");response.getWriter().write("web user has role \"bar\": "+request.isUserInRole("bar") +"\n");response.getWriter().write("web user has role \"kaz\": "+request.isUserInRole("kaz") +"\n"); }}
You can add @BasicAuthenticationMechanismDefinition on a Servlet class or a CDI ApplicationScoped bean.
Here is an example of @FormAuthenticationMechanismDefinition.
@FormAuthenticationMechanismDefinition( loginToContinue = @LoginToContinue( loginPage="/login-servlet", errorPage="/error-servlet" ))@WebServlet("/servlet")@DeclareRoles({ "foo","bar","kaz" })@ServletSecurity(@HttpConstraint(rolesAllowed ="foo"))publicclassTestServletextendsHttpServlet {privatestaticfinallong serialVersionUID =1L; @OverridepublicvoiddoGet(HttpServletRequest request,HttpServletResponse response) throwsServletException,IOException {String webName =null;if (request.getUserPrincipal() !=null) { webName =request.getUserPrincipal().getName(); }response.getWriter().write("<html><body> This is a servlet <br><br>\n"+"web username: "+ webName +"<br><br>\n"+"web user has role \"foo\": "+request.isUserInRole("foo") +"<br>\n"+"web user has role \"bar\": "+request.isUserInRole("bar") +"<br>\n"+"web user has role \"kaz\": "+request.isUserInRole("kaz") +"<br><br>\n"+"<form method=\"POST\">"+"<input type=\"hidden\" name=\"logout\" value=\"true\" >"+"<input type=\"submit\" value=\"Logout\">"+"</form>"+"</body></html>"); } @OverridepublicvoiddoPost(HttpServletRequest request,HttpServletResponse response) throwsServletException,IOException {if ("true".equals(request.getParameter("logout"))) {request.logout();request.getSession().invalidate(); }doGet(request, response); }}
Declare a @FormAuthenticationMechanismDefinition, set LoginToContinue properties.
Note, for a @FormAuthenticationMechanismDefinition, in the login page, form submit action should j_security_check, username field name should be j_username, password field name should be j_password.
This seems a little unreasonable, to free you from these fixed settings, there is a @CustomFormAuthenticationMechanismDefinition, this annotation accept the same properties as @FormAuthenticationMechanismDefinition.