I am going to take another look to the code to see what's happening :S El dj., 9 abr., 2015 a les 15:47, Romain Manni-Bucau (<[email protected]>) va escriure:
> cdi works: > https://git-wip-us.apache.org/repos/asf?p=tomee.git;a=blob; > f=server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/ > CDIProviderContainerRequestFilterTest.java;h= > 6c1802c9e2e825172f550d7793450a81899cfa46;hb=d08f37411b41e19a3e5c2ff1c1620a > cb27c94d5b > > > Romain Manni-Bucau > @rmannibucau <https://twitter.com/rmannibucau> | Blog > <http://rmannibucau.wordpress.com> | Github <https://github.com/ > rmannibucau> | > LinkedIn <https://www.linkedin.com/in/rmannibucau> | Tomitriber > <http://www.tomitribe.com> > > 2015-04-09 11:38 GMT+02:00 Romain Manni-Bucau <[email protected]>: > > > Well not using ejb is surely the current way. They will be reserved for > > scheduling in todays apps i guess. > > Le 9 avr. 2015 10:06, "Alex Soto" <[email protected]> a écrit : > > > >> Ok then I need to implement in two different ways. :( This is something > to > >> improve (I think Java EE 8 is on that way) because security is something > >> transversal so it should be global, not having to implement several > pieces > >> in several places. > >> > >> Well thanks then last option is my option :) > >> > >> El dj., 9 abr., 2015 a les 10:02, Romain Manni-Bucau (< > >> [email protected]>) > >> va escriure: > >> > >> > Hi > >> > > >> > Le 9 avr. 2015 09:15, "Alex Soto" <[email protected]> a écrit : > >> > > > >> > > Hello, I am trying to create an application where I can mix Java EE > >> > > security annotations in JAX-RS endpoints. I am using current TomEE 2 > >> > > Snapshot and basically I am creating two ContainerRequestFilter. > >> > > One for authentication and another for authorization. > >> > > > >> > > @Provider > >> > > @Priority(Priorities.AUTHENTICATION) > >> > > public class JWTAuthenticationFilter implements > >> ContainerRequestFilter { > >> > > > >> > > private static final List<Class<? extends Annotation>> > >> > > securityAnnotations = > >> > > Arrays.asList(DenyAll.class, PermitAll.class, > >> > RolesAllowed.class); > >> > > > >> > > @Context > >> > > private ResourceInfo resourceInfo; > >> > > > >> > > private UserService userservice = new UserService(); > >> > > > >> > > @Override > >> > > public void filter(ContainerRequestContext request) throws > >> > IOException { > >> > > if (isSecuredResource()) { > >> > > > >> > > String token = request.getHeaderString("x- > access-token"); > >> > > > >> > > try { > >> > > String username = getUsernameFromToken(token); > >> > > final User user = userservice.findUser(username); > >> > > > >> > > request.setSecurityContext(new SecurityContext() { > >> > > > >> > > @Override > >> > > public boolean isUserInRole(String role) { > >> > > return user.isUserInRole(role); > >> > > } > >> > > > >> > > @Override > >> > > public boolean isSecure() { > >> > > return false; > >> > > } > >> > > > >> > > @Override > >> > > public Principal getUserPrincipal() { > >> > > return user; > >> > > } > >> > > > >> > > @Override > >> > > public String getAuthenticationScheme() { > >> > > return SecurityContext.BASIC_AUTH; > >> > > } > >> > > }); > >> > > > >> > > } catch (java.text.ParseException | JOSEException | > >> > > NullPointerException e) { > >> > > request.abortWith(Response.status(404).build()); > >> > > } > >> > > } > >> > > } > >> > > > >> > > private boolean isSecuredResource() { > >> > > > >> > > for (Class<? extends Annotation> securityClass : > >> > > securityAnnotations) { > >> > > if (resourceInfo.getResourceMethod(). > isAnnotationPresent( > >> > > securityClass)) { > >> > > return true; > >> > > } > >> > > } > >> > > > >> > > for (Class<? extends Annotation> securityClass : > >> > > securityAnnotations) { > >> > > if (resourceInfo.getResourceClass(). > isAnnotationPresent( > >> > > securityClass)) { > >> > > return true; > >> > > } > >> > > } > >> > > > >> > > return false; > >> > > } > >> > > > >> > > private String getUsernameFromToken(String token) > >> > > throws java.text.ParseException, JOSEException { > >> > > > >> > > SignedJWT signedJWT = SignedJWT.parse(token); > >> > > JWSVerifier verifier = new MACVerifier(SharedSecret. > >> > getSecret()); > >> > > > >> > > if (signedJWT.verify(verifier)) { > >> > > return signedJWT.getJWTClaimsSet().getSubject(); > >> > > } else { > >> > > throw new JOSEException("Firm is not verified."); > >> > > } > >> > > } > >> > > } > >> > > > >> > > > >> > > note that I am creating a custom security context and for > >> authorization: > >> > > > >> > > @Provider > >> > > @Priority(Priorities.AUTHORIZATION) > >> > > public class RolesAllowedFilter implements ContainerRequestFilter { > >> > > > >> > > private static final Response NOT_FOUND = Response.status( > >> > > Response.Status.NOT_FOUND).entity("{\"message\": \"Resource > Not > >> > > Found\"}").build(); > >> > > > >> > > @Context > >> > > private ResourceInfo resourceInfo; > >> > > > >> > > @Override > >> > > public void filter(ContainerRequestContext requestContext) > >> > > throws IOException { > >> > > Method resourceMethod = resourceInfo.getResourceMethod(); > >> > > > >> > > // DenyAll on the method take precedence over RolesAllowed and > >> > PermitAll > >> > > if (resourceMethod.isAnnotationPresent(DenyAll.class)) { > >> > > requestContext.abortWith(NOT_FOUND); > >> > > return; > >> > > } > >> > > > >> > > // RolesAllowed on the method takes precedence over PermitAll > >> > > RolesAllowed ra = > >> resourceMethod.getAnnotation(RolesAllowed.class); > >> > > if(assertRole(requestContext, ra)) { > >> > > return; > >> > > } > >> > > > >> > > // PermitAll takes precedence over RolesAllowed on the class > >> > > if (resourceMethod.isAnnotationPresent(PermitAll.class)) { > >> > > // Do nothing. > >> > > return; > >> > > } > >> > > > >> > > if > >> > (resourceInfo.getResourceClass().isAnnotationPresent(DenyAll.class)) > >> > > { > >> > > requestContext.abortWith(NOT_FOUND); > >> > > } > >> > > > >> > > // RolesAllowed on the class takes precedence over PermitAll > >> > > ra = > >> > resourceInfo.getResourceClass().getAnnotation(RolesAllowed.class); > >> > > if(assertRole(requestContext, ra)) { > >> > > return; > >> > > } > >> > > } > >> > > > >> > > private boolean assertRole(ContainerRequestContext > requestContext, > >> > > RolesAllowed ra) { > >> > > > >> > > if (ra != null) { > >> > > String[] roles = ra.value(); > >> > > for (String role : roles) { > >> > > if (requestContext.getSecurityContext().isUserInRole(role)) > { > >> > > return true; > >> > > } > >> > > } > >> > > requestContext.abortWith(NOT_FOUND); > >> > > } > >> > > return false; > >> > > } > >> > > } > >> > > > >> > > And the business code: > >> > > > >> > > @Stateless > >> > > @Path("/app") > >> > > public class UiApplication { > >> > > > >> > > @Inject > >> > > UserService userService; > >> > > > >> > > @Inject > >> > > MovieService moviesService; > >> > > > >> > > @POST > >> > > @Consumes(MediaType.APPLICATION_JSON) > >> > > @Produces(MediaType.APPLICATION_JSON) > >> > > public Response login(JsonObject jsonObject) throws > JOSEException > >> { > >> > > > >> > > JsonString username = (JsonString) jsonObject.get("username"); > >> > > JsonString password = (JsonString) jsonObject.get("password"); > >> > > > >> > > if (authenticate(username.getString(), > password.getString())) { > >> > > > >> > > String token = createToken(username.getString(), " > example.com > >> "); > >> > > > >> > > JsonObject responseDocument = Json.createObjectBuilder() > >> > > .add("user", Json.createObjectBuilder().add("username", > >> > > username).build()) > >> > > .add("token", token) > >> > > .build(); > >> > > > >> > > return Response.ok(responseDocument).build(); > >> > > > >> > > } > >> > > > >> > > return Response.status(Status.NOT_FOUND).build(); > >> > > > >> > > } > >> > > > >> > > @GET > >> > > @Produces(MediaType.APPLICATION_JSON) > >> > > @RolesAllowed("admin") > >> > > public Response movies() { > >> > > return Response.ok("{\"message\":\"a\"}").build(); > >> > > } > >> > > > >> > > private boolean authenticate(String username, String password) { > >> > > return this.userService.findUser(username, password); > >> > > } > >> > > > >> > > private String createToken(String subject, String issuer) throws > >> > > JOSEException { > >> > > > >> > > JWSSigner signer = new MACSigner(SharedSecret.getSecret()); > >> > > > >> > > JWTClaimsSet claimsSet = new JWTClaimsSet(); > >> > > claimsSet.setSubject(subject); > >> > > claimsSet.setIssueTime(new Date()); > >> > > claimsSet.setIssuer(issuer); > >> > > > >> > > SignedJWT signedJWT = new SignedJWT(new > >> > > JWSHeader(JWSAlgorithm.HS256), claimsSet); > >> > > signedJWT.sign(signer); > >> > > > >> > > return signedJWT.serialize(); > >> > > > >> > > } > >> > > > >> > > } > >> > > > >> > > If I run in this way it doesn't work because the endpoint is also an > >> EJB > >> > > and because security context of EJB is not shared with the JAX-RS, > the > >> > > method throws an 403 Forbidden. Is there any clean way to make that > >> this > >> > > don't happen? Of course I can make JAXRS class as none EJB, but this > >> > would > >> > > be my last option. > >> > > > >> > > >> > Well with @Transactional it would makes sense since you handle > security. > >> > Using jaas would be the way to have custom logic in ejbs. > >> > > >> > > Also is there a way to use @Inject in ContainerRequestFilter? > >> Currently I > >> > > cannot use it because the instance is not injected. > >> > > > >> > > >> > Not yet, dont recall what spec says about it btw > >> > > >> > > Thank you so much. > >> > > > >> > > Alex. > >> > > >> > > >
