package org.javaee7.jacc.contexts.servlet;
import static java.security.Policy.getPolicy;
import static java.util.Collections.list;
import java.io.IOException;
import java.security.CodeSource;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.Principal;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;
import java.util.HashSet;
import java.util.Set;
import javax.security.auth.Subject;
import javax.security.jacc.PolicyContext;
import javax.security.jacc.PolicyContextException;
import javax.security.jacc.WebRoleRefPermission;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* This Servlet demonstrates both how to obtain the Subject and then how to retrieve the roles from
* this Subject.
*
* @author Arjan Tijms
*
*/
@WebServlet(urlPatterns = "/subjectServlet")
public class SubjectServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
Subject subject = (Subject) PolicyContext.getContext("javax.security.auth.Subject.container");
if (subject != null) {
response.getWriter().print("Obtained subject from context.\n");
// Get the permissions associated with the Subject we obtained
PermissionCollection permissionCollection = getPermissionCollection(subject);
// Resolve any potentially unresolved permissions
permissionCollection.implies(new WebRoleRefPermission("", "nothing"));
// Filter just the roles from all the permissions, which may include things like
// java.net.SocketPermission, java.io.FilePermission, and obtain the actual role names.
Set<String> roles = filterRoles(request, permissionCollection);
for (String role : roles) {
response.getWriter().print("User has role " + role + "\n");
}
}
} catch (PolicyContextException e) {
e.printStackTrace(response.getWriter());
}
}
private PermissionCollection getPermissionCollection(Subject subject) {
return getPolicy().getPermissions(
new ProtectionDomain(
new CodeSource(null, (Certificate[]) null),
null, null,
subject.getPrincipals().toArray(new Principal[subject.getPrincipals().size()])
)
);
}
private Set<String> filterRoles(HttpServletRequest request, PermissionCollection permissionCollection) {
Set<String> roles = new HashSet<>();
for (Permission permission : list(permissionCollection.elements())) {
if (permission instanceof WebRoleRefPermission) {
String role = permission.getActions();
// Note that the WebRoleRefPermission is given for every Servlet in the application, even when
// no role refs are used anywhere. This will also include Servlets like the default servlet and the
// implicit JSP servlet. So if there are 2 application roles, and 3 application servlets, then
// at least 6 WebRoleRefPermission elements will be present in the collection.
if (!roles.contains(role) && request.isUserInRole(role)) {
roles.add(role);
}
}
}
return roles;
}
}