Follow these steps to complete this recipe:
- First, we will define some roles in a separate class so that we can reuse it:
public class Roles {
public static final String ROLE1 = "role1";
public static final String ROLE2 = "role2";
public static final String ROLE3 = "role3";
}
- Then, we need to define some things that the application's users can do:
@Stateful
public class UserActivity {
@RolesAllowed({Roles.ROLE1})
public void role1Allowed(){
System.out.println("role1Allowed executed");
}
@RolesAllowed({Roles.ROLE2})
public void role2Allowed(){
System.out.println("role2Allowed executed");
}
@RolesAllowed({Roles.ROLE3})
public void role3Allowed(){
System.out.println("role3Allowed executed");
}
@PermitAll
public void anonymousAllowed(){
System.out.println("anonymousAllowed executed");
}
@DenyAll
public void noOneAllowed(){
System.out.println("noOneAllowed executed");
}
}
- Let's create an interface for executable tasks:
public interface Executable {
void execute() throws Exception;
}
- Now, let's create another for the roles that will execute them:
public interface RoleExecutable {
void run(Executable executable) throws Exception;
}
- We need to create an executor for each role. An executor is like an environment that owns the rights of that role:
@Named
@RunAs(Roles.ROLE1)
public class Role1Executor implements RoleExecutable {
@Override
public void run(Executable executable) throws Exception {
executable.execute();
}
}
@Named
@RunAs(Roles.ROLE2)
public class Role2Executor implements RoleExecutable {
@Override
public void run(Executable executable) throws Exception {
executable.execute();
}
}
@Named
@RunAs(Roles.ROLE3)
public class Role3Executor implements RoleExecutable {
@Override
public void run(Executable executable) throws Exception {
executable.execute();
}
}
- Then, we implement HttpAuthenticationMechanism:
@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 (null == callerOnlyCredential.getCaller()) {
throw new AuthenticationException();
} else switch (callerOnlyCredential.getCaller()) {
case "user1":
return
httpMessageContext.
notifyContainerAboutLogin
(callerOnlyCredential.getCaller(),
new HashSet<>
(asList(Roles.ROLE1)));
case "user2":
return
httpMessageContext.
notifyContainerAboutLogin
(callerOnlyCredential.getCaller(),
new HashSet<>
(asList(Roles.ROLE2)));
case "user3":
return
httpMessageContext.
notifyContainerAboutLogin
(callerOnlyCredential.getCaller(),
new HashSet<>
(asList(Roles.ROLE3)));
default:
throw new AuthenticationException();
}
}
return httpMessageContext.doNothing();
}
}
- Finally, we create the servlet that will manage all these resources:
@DeclareRoles({Roles.ROLE1, Roles.ROLE2, Roles.ROLE3})
@WebServlet(name = "/UserAuthorizationServlet", urlPatterns = {"/UserAuthorizationServlet"})
public class UserAuthorizationServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Inject
private SecurityContext securityContext;
@Inject
private Role1Executor role1Executor;
@Inject
private Role2Executor role2Executor;
@Inject
private Role3Executor role3Executor;
@Inject
private UserActivity userActivity;
@Override
public void doGet(HttpServletRequest request,
HttpServletResponse
response) throws ServletException, IOException {
try {
String name = request.getParameter("name");
if (null != name || !"".equals(name)) {
AuthenticationStatus status =
securityContext.authenticate(
request, response, withParams().credential(
new CallerOnlyCredential(name)));
response.getWriter().write("Authentication
status: " + status.name() + "\n");
}
String principal = null;
if (request.getUserPrincipal() != null) {
principal = request.getUserPrincipal().getName();
}
response.getWriter().write("User: " + principal +
"\n");
response.getWriter().write("Role \"role1\" access: " +
request.isUserInRole(Roles.ROLE1) + "\n");
response.getWriter().write("Role \"role2\" access: " +
request.isUserInRole(Roles.ROLE2) + "\n");
response.getWriter().write("Role \"role3\" access: " +
request.isUserInRole(Roles.ROLE3) + "\n");
RoleExecutable executable = null;
if (request.isUserInRole(Roles.ROLE1)) {
executable = role1Executor;
} else if (request.isUserInRole(Roles.ROLE2)) {
executable = role2Executor;
} else if (request.isUserInRole(Roles.ROLE3)) {
executable = role3Executor;
}
if (executable != null) {
executable.run(() -> {
try {
userActivity.role1Allowed();
response.getWriter().write("role1Allowed
executed: true\n");
} catch (Exception e) {
response.getWriter().write("role1Allowed
executed: false\n");
}
try {
userActivity.role2Allowed();
response.getWriter().write("role2Allowed
executed: true\n");
} catch (Exception e) {
response.getWriter().write("role2Allowed
executed: false\n");
}
try {
userActivity.role3Allowed();
response.getWriter().write("role2Allowed
executed: true\n");
} catch (Exception e) {
response.getWriter().write("role2Allowed
executed: false\n");
}
});
}
try {
userActivity.anonymousAllowed();
response.getWriter().write("anonymousAllowed
executed: true\n");
} catch (Exception e) {
response.getWriter().write("anonymousAllowed
executed: false\n");
}
try {
userActivity.noOneAllowed();
response.getWriter().write("noOneAllowed
executed: true\n");
} catch (Exception e) {
response.getWriter().write("noOneAllowed
executed: false\n");
}
} catch (Exception ex) {
System.err.println(ex.getMessage());
}
}
}
To try this code out, run the following URLs:
- http://localhost:8080/ch05-authorization/UserAuthorizationServlet?name=user1
- http://localhost:8080/ch05-authorization/UserAuthorizationServlet?name=user2
- http://localhost:8080/ch05-authorization/UserAuthorizationServlet?name=user3
The result for user1, for example, will be as follows:
Authentication status: SUCCESS
User: user1
Role "role1" access: true
Role "role2" access: false
Role "role3" access: false
role1Allowed executed: true
role2Allowed executed: false
role2Allowed executed: false
anonymousAllowed executed: true
noOneAllowed executed: false
If you try this out with a user that doesn't exist, the result will be as follows:
Authentication status: SEND_FAILURE
User: null
Role "role1" access: false
Role "role2" access: false
Role "role3" access: false
anonymousAllowed executed: true
noOneAllowed executed: false