I have a resource class as
#Path("secure")
#RequestScoped
// #SecurityChecked
public class SecureResource {
#Context
private HttpServletRequest request;
#GET
#SecurityChecked
public Response getUser() {
return Response.ok("authenticated successfully!").build();
}
#POST
public Response login(#FormParam("user") #Nonnull final String user,
#FormParam("password") #Nonnull final String password) {
final String authToken = TokenUtils.createToken(user);
return Response.ok().header(AUTH_TOKEN, authToken).build();
}
#PUT
public Response updateUser() {
return Response.ok("updating user").build();
}
}
and I have a PostProcessInterceptor where I would like to access the request of header class
#Interceptor
#Provider
#ServerInterceptor
#SecurityChecked
public class SecurityCheckInterceptor implements PostProcessInterceptor {
private static final Pattern PATTERN = Pattern.compile(":");
private static final Logger LOGGER = LoggerFactory.getLogger(SecurityCheckInterceptor.class);
#Override
public void postProcess(final ServerResponse response) {
// access the Resource class request object
}
}
I am not sure how can I access the request object here
Please help
Thank you
Why do you want to access request in PostProcessInterceptor? Are you sure you cant use
public static class MyInterceptor implements PreProcessInterceptor{
...
#Override
public ServerResponse preProcess(HttpRequest request, ResourceMethod method){...}
}
here?
Related
I have a REST-Backend created with JHipster. There are different exception-classes in the service layer and the web-rest layer. This service-exceptions are translated by an ExceptionTranslator which implements the ProblemHandling interface from org.zalando.problem.spring.web.advice
I have the following ExceptionTranslator:
#ControllerAdvice
public class ExceptionTranslator implements ProblemHandling, SecurityAdviceTrait {
#Override
public ResponseEntity<Problem> process(#Nullable ResponseEntity<Problem> entity, NativeWebRequest request) {
//generated by jHipster
}
#ExceptionHandler(HouseWithoutOwnerServiceException.class)
public ResponseEntity<Problem> handleHouseWithoutOwnerException(HouseWithoutOwnerServiceException ex, NativeWebRequest request) {
return create(new HouseWithoutOwnerException(), request);
}
}
The service-exception class:
public class HouseWithoutOwnerServiceException extends RuntimeException {
public HouseWithoutOwnerServiceException() {
super("House without owner!");
}
}
The rest-error class:
public class HouseWithoutOwnerException extends AbstractThrowableProblem {
private static final long serialVersionUID = 1L;
public HouseWithoutOwnerException() {
super(ErrorConstants.HOUSE_WITHOUT_OWNER_TYPE, "House does not have an owner", Status.CONFLICT);
}
}
In my test the HouseWithoutOwnerServiceException is thrown but not translated into a HouseWithoutOwnerException:
#SpringBootTest(classes = HouseApp.class)
public class HouseControllerIT {
#Autowired
private MappingJackson2HttpMessageConverter jacksonMessageConverter;
#Autowired
private PageableHandlerMethodArgumentResolver pageableArgumentResolver;
#Autowired
private ExceptionTranslator exceptionTranslator;
private MockMvc restHouseMockMvc;
#BeforeEach
public void setup() {
HouseController houseController = new HouseController(houseService);
this.restHouseMockMvc = MockMvcBuilders.standaloneSetup(houseController)
.setCustomArgumentResolvers(pageableArgumentResolver)
.setControllerAdvice(exceptionTranslator)
.setMessageConverters(jacksonMessageConverter)
.build();
}
#Test
#Transactional
public void createHouseWithoutExistingOwner() throws Exception {
HouseDTO houseDTO = createHouseDTOWithoutOwner();
houseDTO.setOwnerId(ownerId + 1); //not existing
restHouseMockMvc.perform(post("/api/v1/houses")
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(houseDTO)))
.andExpect(status().isConflict());
}
}
Therefore I always get 500 Internal Server Error instead of 409 Conflict. I debugged it already and the method in the ExceptionTranslator is not entered.
I have this class and wants to log the rest-requests:
public class RequestFilter implements ContainerRequestFilter {
private static final Logger LOG = LoggerFactory.getLogger(RequestFilter.class);
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
LOG.info("REST-Request from '{}' for '{}'", "XXX", requestContext.getUriInfo().getPath());
// ... and do some auth stuff (not relevant for this question)
}
}
How do do I get the remote IP of the request? TIA!
Try this:
public class RequestFilter implements ContainerRequestFilter {
private static final Logger LOG = LoggerFactory.getLogger(RequestFilter.class);
#Context
private HttpServletRequest request;
// rest of your stuff here
A late reply, but this may help others using Grizzly2 ...
import javax.servlet.http.HttpServletRequest;
import org.glassfish.grizzly.http.server.Request;
public class RequestFilter implements ContainerRequestFilter {
private static final Logger LOG = LoggerFactory.getLogger(RequestFilter.class);
#Context
private HttpServletRequest httpServletRequest;
#Inject
private Provider<Request> grizzlyRequest;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
String remoteIpAddress;
if (httpServletRequest != null) {
// JSR-315/JSR-339 compliant server
remoteIpAddress = httpServletRequest.getRemoteAddr();
} else {
// Grizzly2 server
remoteIpAddress = grizzlyRequest.get().getRemoteAddr();
}
I am developing a REST API using Jersey 2 and at the moment I am trying to incorporate basic authentication by use of an annotation similar to the #Auth found in Dropwizard. With
#Path("hello")
public class HelloResource {
#GET
#Produces("application/json")
public String hello(#Auth final Principal principal) {
return principal.getUsername();
}
}
the hello resource invocation should be intercepted by some code performing basic authentication using the credentials passed in the Authorization HTTP request header and on success injecting the principal into the method principal parameter.
I have started creating an #Auth resolver, see below, but I do not see how I can access the Authorization HTTP request header from within that?
#Singleton
public class AuthResolver {
public static class AuthInjectionResolver extends ParamInjectionResolver<Auth> {
public AuthInjectionResolver() {
super(AuthValueFactoryProvider.class);
}
}
#Singleton
public static class AuthValueFactoryProvider extends AbstractValueFactoryProvider {
#Inject
public AuthValueFactoryProvider(final MultivaluedParameterExtractorProvider extractorProvider, final ServiceLocator injector) {
super(extractorProvider, injector, UNKNOWN);
}
#Override
protected Factory<?> createValueFactory(final Parameter parameter) {
final Class<?> classType = parameter.getRawType();
return classType == null || !classType.equals(Principal.class) ? null :
new AbstractContainerRequestValueFactory<Principal>() {
#Override
public Principal provide() {
// Authentication?
}
};
}
}
public static class Binder extends AbstractBinder {
#Override
protected void configure() {
bind(AuthValueFactoryProvider.class).to(ValueFactoryProvider.class).in(Singleton.class);
bind(AuthInjectionResolver.class).to(
new TypeLiteral<InjectionResolver<Auth>>() {
}
).in(Singleton.class);
}
}
}
How to approach this? :)
Ah, in AbstractContainerRequestValueFactory<Principal> I can add
#Context private ResourceContext context;
and then extract the HTTP request and it's headers from there inside the provide method.
We have a problem with our tests that the field UriInfo is not correctly injected when the resource is wrapped in a TransactionalProxy.
We tried using the SpringResourceFactory but that did not help either.
I tried to extract the relevant classes for this usecase:
public class InMemoryClientFactory implements FactoryBean<InMemoryClientExecutor>{
#Inject
private SessionResource sessionResource;
#Override
public InMemoryClientExecutor getObject() throws Exception {
Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
Registry registry = dispatcher.getRegistry();
registry.addSingletonResource(sessionResource);
final InMemoryClientExecutor inMemoryClientExecutor = new InMemoryClientExecutor(dispatcher);
}
#Override
public Class getObjectType() {
return InMemoryClientExecutor.class;
}
#Override
public boolean isSingleton() {
return true;
}
}
#Path("session")
public interface SessionResource {
#GET
#Path("{sessionId}")
#Produces({MediaType.APPLICATION_XML})
Response get(#PathParam("sessionId") String sessionId);
#DELETE
#Path("{sessionId}")
Response delete(#PathParam("sessionId") String sessionId);
}
#Service
#Transactional
public class SessionResourceImpl implements SessionResource {
#Context
private UriInfo uriInfo;
#Override
public Response get(String sessionId) {
// uriInfo will be null here
String url = uriInfo.getBaseUriBuilder().path(SessionResource.class).path(SessionResource.class, "delete").build(sessionId)
.toString());
return Response.ok(session).build();
#Override
public Response delete(String sessionId) {
System.out.println("Deleted Session "+1);
}
}
#ContextConfiguration(locations = ["classpath:/META-INF/testContext.xml"])
#Transactional
#RunWith(SpringJUnit4ClassRunner.class)
public class SessionResourceIT {
#Inject
InMemoryRestClientFactory inMemoryClientFactory;
#Inject
SessionResource resource;
#Test
public void test() {
SessionResource resource = inMemoryClientFactory.createProxy(SessionResource.class);
ClientResponse cr = client.get(sessionId);
assertNotNull(cr.getEntity(String.class));
}
}
A possible workaround is to unwrap the transactional proxy for the tests, this works as long as the test itself is annotated with #Transactional. I hope someone has a better solution than this.
public class InMemoryClientFactory implements FactoryBean<InMemoryClientExecutor>{
#Inject
private SessionResource sessionResource;
#Override
public InMemoryClientExecutor getObject() throws Exception {
Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
Registry registry = dispatcher.getRegistry();
registry.addSingletonResource(unwrapProxy(sessionResource));
final InMemoryClientExecutor inMemoryClientExecutor = new InMemoryClientExecutor(dispatcher);
}
#Override
public Class getObjectType() {
return InMemoryClientExecutor.class;
}
#Override
public boolean isSingleton() {
return true;
}
private static Object unwrapProxy(Object bean) throws Exception {
Object result = bean;
/*
* If the given object is a proxy, set the return value as the object
* being proxied, otherwise return the given object.
*/
if (AopUtils.isAopProxy(bean) && bean instanceof Advised) {
Advised advised = (Advised) bean;
result = advised.getTargetSource().getTarget();
}
return result;
}
}
Setting Attribute
public class VoucherApproverListAction extends ActionSupport implements
SessionAware, ServletRequestAware, Preparable {
private HttpServletRequest servletRequest;
public HttpServletRequest getServletRequest() {
return servletRequest;
}
#Override
public void setServletRequest(HttpServletRequest servletRequest) {
this.servletRequest=servletRequest;
}
public void prepare() throws Exception {
servletRequest.setAttribute("id",tCaseVouchrDto.getId());
}
}
Getting Attribute
public class VoucherAction extends ActionSupport implements
SessionAware, ServletRequestAware, Preparable {
private HttpServletRequest servletRequest;
public HttpServletRequest getServletRequest() {
return servletRequest;
}
#Override
public void setServletRequest(HttpServletRequest servletRequest) {
this.servletRequest=servletRequest;
}
public void prepare() throws Exception {
String paramValue = (String)servletRequest.getAttribute("id");
logger.info("#-----Id===-----#" + paramValue);
}
}
From VoucherApproverListAction action class after success ,it is redirected to VoucherAction action class Getting null in paramValue
From VoucherApproverListAction action class after success ,it is
redirected to VoucherAction action class
This is the problem, request attributes are lost if you send redirect. You need to pass a parameter or save it in the session before the next request.