Follow these steps to complete this recipe:
- First, let's define our roles list:
public class Roles {
public static final String ADMIN = "admin";
public static final String USER = "user";
}
- Now, let's define a list of tasks to be completed based on the role:
@Stateful
public class UserBean {
@RolesAllowed({Roles.ADMIN})
public void adminOperation(){
System.out.println("adminOperation executed");
}
@RolesAllowed({Roles.USER})
public void userOperation(){
System.out.println("userOperation executed");
}
@PermitAll
public void everyoneCanDo(){
System.out.println("everyoneCanDo executed");
}
}
- Now, let's implement the IndentityStore interface. Here, we define our policy so that we can validate the user's identity:
@ApplicationScoped
public class UserIdentityStore implements IdentityStore {
@Override
public CredentialValidationResult validate(Credential credential) {
if (credential instanceof UsernamePasswordCredential) {
return validate((UsernamePasswordCredential) credential);
}
return CredentialValidationResult.NOT_VALIDATED_RESULT;
}
public CredentialValidationResult validate(UsernamePasswordCredential
usernamePasswordCredential) {
if (usernamePasswordCredential.
getCaller().equals(Roles.ADMIN)
&& usernamePasswordCredential.
getPassword().compareTo("1234"))
{
return new CredentialValidationResult(
new CallerPrincipal
(usernamePasswordCredential.getCaller()),
new HashSet<>(Arrays.asList(Roles.ADMIN)));
} else if (usernamePasswordCredential.
getCaller().equals(Roles.USER)
&& usernamePasswordCredential.
getPassword().compareTo("1234"))
{
return new CredentialValidationResult(
new CallerPrincipal
(usernamePasswordCredential.getCaller()),
new HashSet<>(Arrays.asList(Roles.USER)));
}
return CredentialValidationResult.INVALID_RESULT;
}
}
- Here, we need to implement the HttpAuthenticationMethod interface:
@ApplicationScoped
public class AuthenticationMechanism implements HttpAuthenticationMechanism {
@Inject
private UserIdentityStore identityStore;
@Override
public AuthenticationStatus validateRequest(HttpServletRequest
request,
HttpServletResponse response, HttpMessageContext
httpMessageContext)
throws AuthenticationException {
if (httpMessageContext.isAuthenticationRequest()) {
Credential credential =
httpMessageContext.getAuthParameters()
.getCredential();
if (!(credential instanceof UsernamePasswordCredential)) {
throw new IllegalStateException("Invalid
mechanism");
}
return httpMessageContext.notifyContainerAboutLogin
(identityStore.validate(credential));
}
return httpMessageContext.doNothing();
}
}
- Finally, we need to create a servlet where the user will both authenticate and carry out their tasks:
@DeclareRoles({Roles.ADMIN, Roles.USER})
@WebServlet(name = "/OperationServlet", urlPatterns = {"/OperationServlet"})
public class OperationServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Inject
private SecurityContext securityContext;
@Inject
private UserBean userActivity;
@Override
public void doGet(HttpServletRequest request,
HttpServletResponse
response) throws ServletException, IOException {
String name = request.getParameter("name");
String password = request.getParameter("password");
Credential credential = new UsernamePasswordCredential(name,
new Password(password));
AuthenticationStatus status = securityContext.authenticate(
request, response,
withParams().credential(credential));
response.getWriter().write("Role \"admin\" access: " +
request.isUserInRole(Roles.ADMIN) + "\n");
response.getWriter().write("Role \"user\" access: " +
request.isUserInRole(Roles.USER) + "\n");
if (status.equals(AuthenticationStatus.SUCCESS)) {
if (request.isUserInRole(Roles.ADMIN)) {
userActivity.adminOperation();
response.getWriter().write("adminOperation
executed: true\n");
} else if (request.isUserInRole(Roles.USER)) {
userActivity.userOperation();
response.getWriter().write("userOperation
executed: true\n");
}
userActivity.everyoneCanDo();
response.getWriter().write("everyoneCanDo
executed: true\n");
} else {
response.getWriter().write("Authentication failed\n");
}
}
}
To try out this code, run it in a Jakarta EE 8-compatible server using the following URLs:
- http://localhost:8080/ch05-programmatic/OperationServlet?name=user&password=1234
- http://localhost:8080/ch05-programmatic/OperationServlet?name=admin&password=1234
- An example of the ADMIN role's result is as follows:
Role "admin" access: true
Role "user" access: false
adminOperation executed: true
everyoneCanDo executed: true
- If you use a wrong username/password pair, you'll get the following result:
Role "admin" access: false
Role "user" access: false
Authentication failed