Follow these steps to complete this recipe:
- First, make some configuration changes in the web.xml file:
<security-constraint>
<web-resource-collection>
<web-resource-name>CH05-Authentication</web-resource-name>
<url-pattern>/authServlet</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>role1</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>role1</role-name>
</security-role>
- Next, create a servlet that will deal with our user access:
@DeclareRoles({"role1", "role2", "role3"})
@WebServlet(name = "/UserAuthenticationServlet", urlPatterns = {"/UserAuthenticationServlet"})
public class UserAuthenticationServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Inject
private javax.security.enterprise.SecurityContext
securityContext;
@Override
public void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
String name = request.getParameter("name");
if (null != name || !"".equals(name)) {
AuthenticationStatus status =
securityContext.authenticate(
request, response,
AuthenticationParameters.withParams().credential
(new CallerOnlyCredential(name)));
response.getWriter().write("Authentication status: "
+ status.name() + " ");
}
String principal = null;
if (request.getUserPrincipal() != null) {
principal = request.getUserPrincipal().getName();
}
response.getWriter().write("User: " + principal + " ");
response.getWriter().write("Role "role1" access: " +
request.isUserInRole("role1") + " ");
response.getWriter().write("Role "role2" access: " +
request.isUserInRole("role2") + " ");
response.getWriter().write("Role "role3" access: " +
request.isUserInRole("role3") + " ");
response.getWriter().write("Access to /authServlet? " +
securityContext.hasAccessToWebResource("/authServlet") +
" ");
}
}
- Finally, we will create a class that will define our authentication policy:
@ApplicationScoped
public class AuthenticationMechanism implements
HttpAuthenticationMechanism {
@Override
public AuthenticationStatus validateRequest(HttpServletRequest
request,
HttpServletResponse response, HttpMessageContext
httpMessageContext)
throws AuthenticationException {
if (httpMessageContext.isAuthenticationRequest()) {
Credential credential =
httpMessageContext.getAuthParameters().getCredential();
if (!(credential instanceof CallerOnlyCredential)) {
throw new IllegalStateException("Invalid
mechanism");
}
CallerOnlyCredential callerOnlyCredential =
(CallerOnlyCredential) credential;
if ("user".equals(callerOnlyCredential.getCaller())) {
return
httpMessageContext.notifyContainerAboutLogin
(callerOnlyCredential.getCaller(), new HashSet<>
(Arrays.asList("role1","role2")));
} else{
throw new AuthenticationException();
}
}
return httpMessageContext.doNothing();
}
}
If you run this project in a Jakarta EE 8-compatible server, you should use the following URL (assuming that you are running locally; if not, make the appropriate changes):
http://localhost:8080/ch05-authentication/UserAuthenticationServlet?name=user
- This should result in a page that shows the following messages:
Authentication status: SUCCESS
User: user
Role "role1" access: true
Role "role2" access: true
Role "role3" access: false
Access to /authServlet? true
Try making a change to the name parameter, as follows:
http://localhost:8080/ch05-authentication/UserAuthenticationServlet?name=anotheruser
- The result will be as follows:
Authentication status: SEND_FAILURE
User: null
Role "role1" access: false
Role "role2" access: false
Role "role3" access: false
Access to /authServlet? false
Now, let's see how this works.