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.
> >> >
> >>
> >
>

Reply via email to