Java JAX-RS Name Binding Not working - java

I am working on an authentication filter for my REST service.
Can some one please explain why this name binding not works.
When I make a post request, I can receive the String "Tokenized", but log does not print "Inside the filter".
import java.io.IOException;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.FormParam;
import javax.ws.rs.NameBinding;
import javax.ws.rs.Produces;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Target;
import javax.annotation.Priority;
import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.ext.Provider;
import org.apache.log4j.Logger;
#Path("/authentication")
public class AuthenticationHandler {
final static Logger log = Logger.getLogger(AuthenticationHandler.class);
#NameBinding
#Retention(RUNTIME)
#Target({TYPE, METHOD})
public #interface Secured {
}
#Secured
#Provider
#Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
log.info("Inside the filter");
// Get the HTTP Authorization header from the request
String authorizationHeader
= requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
// Check if the HTTP Authorization header is present and formatted correctly
if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
throw new NotAuthorizedException("Authorization header must be provided");
}
// Extract the token from the HTTP Authorization header
String token = authorizationHeader.substring("Bearer".length()).trim();
try {
// Validate the token
validateToken(token);
} catch (Exception e) {
requestContext.abortWith(
Response.status(Response.Status.UNAUTHORIZED).build());
}
}
private void validateToken(String token) throws Exception {
// Check if it was issued by the server and if it's not expired
// Throw an Exception if the token is invalid
}
}
#POST
#Secured
#Path("/request_token")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response authenticateUser(#FormParam("username") String username,
#FormParam("password") String password) {
try {
// Authenticate the user using the credentials provided
authenticate(username, password);
// Issue a token for the user
String token = issueToken(username);
// Return the token on the response
return Response.ok(token).build();
} catch (Exception e) {
return Response.status(Response.Status.UNAUTHORIZED).build();
}
}
private boolean authenticate(String username, String password) throws Exception {
return true;
}
private String issueToken(String username) {
return "Tokenized";
}
}

Thanks for the tip peeskillet.
It is now working fine after creating separate classes for Name Bind and Filter. I'm posting the solution below if anyone required.
My problem now is, is there a way to keep this two classes in a separate package, because I tried by putting it on my Util package and it didn't work properly.
peeskillet : Thanks for the tip again.
AuthenticationFilter.java
import com.binosaurs.sf.backend.handler.Secured;
import com.binosaurs.sf.backend.util.*;
import java.io.IOException;
import javax.annotation.Priority;
import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import org.apache.log4j.Logger;
#Secured
#Provider
#Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
// Get Log4j Logger
final static Logger log = Logger.getLogger(AuthenticationFilter.class);
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
log.info("Inside the filter");
// Get the HTTP Authorization header from the request
String authorizationHeader
= requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
// Check if the HTTP Authorization header is present and formatted correctly
if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
throw new NotAuthorizedException("Authorization header must be provided");
}
// Extract the token from the HTTP Authorization header
String token = authorizationHeader.substring("Bearer".length()).trim();
try {
// Validate the token
validateToken(token);
} catch (Exception e) {
requestContext.abortWith(
Response.status(Response.Status.UNAUTHORIZED).build());
}
}
private void validateToken(String token) throws Exception {
// Check if it was issued by the server and if it's not expired
// Throw an Exception if the token is invalid
}
}
Secured.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.binosaurs.sf.backend.handler;
import com.binosaurs.sf.backend.util.*;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Target;
import javax.ws.rs.NameBinding;
#NameBinding
#Retention(RUNTIME)
#Target({TYPE, METHOD})
public #interface Secured {
}
AuthenticationHandler.java
package com.binosaurs.sf.backend.handler;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.FormParam;
import javax.ws.rs.Produces;
import org.apache.log4j.Logger;
#Path("/authentication")
public class AuthenticationHandler {
final static Logger log = Logger.getLogger(AuthenticationHandler.class);
#POST
#Secured
#Path("/request_token")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response authenticateUser(#FormParam("username") String username,
#FormParam("password") String password) {
try {
// Authenticate the user using the credentials provided
authenticate(username, password);
// Issue a token for the user
String token = issueToken(username);
// Return the token on the response
return Response.ok(token).build();
} catch (Exception e) {
return Response.status(Response.Status.UNAUTHORIZED).build();
}
}
private boolean authenticate(String username, String password) throws Exception {
return true;
}
private String issueToken(String username) {
return "Tokenized";
}
}

Related

Jwt Auth controller is not generating Jwt Token just showing an empty { } i am using swaggerUI

' Hello,
I have 2 problems with this code now.
In auth Controller, the JWT token generator is empty just showing this {}. It should show
{"username ": "string " , "password" : "string" }
Once is registered through auth controller and checked in Database in Role it is generating a row and id =0 and name= null but it suppose to assign either Normal/Admin right. Also when I try to register 2nd time it gets an error as Internal server error, please help me with this. '
package com.mohammedkhadeer.blog.controllers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.mohammedkhadeer.blog.exceptions.ApiException;
import com.mohammedkhadeer.blog.payloads.JwtAuthRequest;
import com.mohammedkhadeer.blog.payloads.JwtAuthResponse;
import com.mohammedkhadeer.blog.payloads.UserDto;
import com.mohammedkhadeer.blog.security.JwtTokenHelper;
import com.mohammedkhadeer.blog.services.UserService;
#RestController
#RequestMapping("/api/v1/auth/")
public class AuthController {
#Autowired
private JwtTokenHelper jwtTokenHelper;
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private UserService userService;
#PostMapping("/login")
public ResponseEntity<JwtAuthResponse> createToken(#RequestBody JwtAuthRequest request) throws Exception {
this.authenticate(request.getUsername(), request.getPassword());
UserDetails userDetails = this.userDetailsService.loadUserByUsername(request.getUsername());
String token = this.jwtTokenHelper.generateToken(userDetails);
JwtAuthResponse response = new JwtAuthResponse();
response.setToken(token);
return new ResponseEntity<JwtAuthResponse>(response, HttpStatus.OK);
}
private void authenticate(String username, String password) throws Exception {
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username,
password);
try {
this.authenticationManager.authenticate(authenticationToken);
} catch (BadCredentialsException e) {
System.out.println("Invalid Detials !!");
throw new ApiException("Invalid username or password !!");
}
}
// register new user api
#PostMapping("/register")
public ResponseEntity<UserDto> registerUser(#RequestBody UserDto userDto) {
UserDto registeredUser = this.userService.registerNewUser(userDto);
return new ResponseEntity<UserDto>(registeredUser, HttpStatus.CREATED);
}
}
package com.mohammedkhadeer.blog.security;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
#Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private JwtTokenHelper jwtTokenHelper;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// 1. get token
String requestToken = request.getHeader("Authorization");
// Bearer 2352523sdgsg
System.out.println(requestToken);
String username = null;
String token = null;
if (requestToken != null && requestToken.startsWith("Bearer")) {
token = requestToken.substring(7);
try {
username = this.jwtTokenHelper.getUsernameFromToken(token);
} catch (IllegalArgumentException e) {
System.out.println("Unable to get Jwt token");
} catch (ExpiredJwtException e) {
System.out.println("Jwt token has expired");
} catch (MalformedJwtException e) {
System.out.println("invalid jwt");
}
} else {
System.out.println("Jwt token does not begin with Bearer");
}
// once we get the token , now validate
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (this.jwtTokenHelper.validateToken(token, userDetails)) {
// shi chal rha hai
// authentication karna hai
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
} else {
System.out.println("Invalid jwt token");
}
} else {
System.out.println("username is null or context is not null");
}
filterChain.doFilter(request, response);
}
}
package com.mohammedkhadeer.blog;
import java.util.List;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import com.mohammedkhadeer.blog.config.AppConstants;
import com.mohammedkhadeer.blog.entities.Role;
import com.mohammedkhadeer.blog.repositories.RoleRepo;
#SpringBootApplication
public class BlogAppApisApplication implements CommandLineRunner {
#Autowired
private PasswordEncoder passwordEncoder;
#Autowired
private RoleRepo roleRepo;
public static void main(String[] args) {
SpringApplication.run(BlogAppApisApplication.class, args);
}
#Bean
public ModelMapper modelMapper() {
return new ModelMapper();
}
#Override
public void run(String... args) throws Exception {
System.out.println(this.passwordEncoder.encode("xyz"));
try {
Role role = new Role();
role.setId(AppConstants.ADMIN_USER);
role.setName("ROLE_ADMIN");
Role role1 = new Role();
role1.setId(AppConstants.NORMAL_USER);
role1.setName("ROLE_NORMAL");
List<Role> roles = List.of(role, role1);
List<Role> result = this.roleRepo.saveAll(roles);
result.forEach(r -> {
System.out.println(r.getName());
});
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}

Angular Response Header Read Error, Null Object on response

I have backend in spring, and front end in angular. I have problem to access a authorization header. In postman if i ping localhost:8080/login wiht correct data i get success authorization, but in my appliaction when i try to post with httpclient localhost:8080/login with correct data i get success response but without token in header, headers are be null.
Angular AuthService:
import { Injectable } from '#angular/core';
import { HttpClient, HttpErrorResponse, HttpHeaders, HttpResponse } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class AuthService {
/** Data */
token!: string;
logged = false;
/** Constructor */
constructor(private http: HttpClient) { }
/** Authentiacate User */
login(username: string, password: string): void {
const credentials: LoginCredentials = {
username,
password
};
this.http.post('http://localhost:8080/login',
JSON.stringify(credentials), { observe: 'response' }).subscribe(res => {
// Not works... Authorization header is null object
console.log('Authorized success!' + res.headers.get('Authorization'));
this.logged = true;
},
(error: HttpErrorResponse) => {
console.log('Nie udana autoryzacja! KOD BLEDU: ' + error.status);
});
}
}
/** LoginCredentials */
interface LoginCredentials {
username: string;
password: string;
}
Spring AuthorizationFilter, SuccessHandler, SecurityConfig
package com.revo.ToDoList.handler;
import java.io.IOException;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.revo.ToDoList.config.SecurityConfig;
import com.revo.ToDoList.model.User;
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
/*
* On success authentication add token to header
*/
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
String token = JWT.create().withSubject(((User) authentication.getPrincipal()).getUsername())
.withExpiresAt(new Date(System.currentTimeMillis() + SecurityConfig.expirationTime)).sign(Algorithm.HMAC256(SecurityConfig.secret));
response.addHeader("Authorization", "Bearer " + token);
}
}
package com.revo.ToDoList.filter;
import java.io.BufferedReader;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.revo.ToDoList.model.LoginCredentials;
public class MyAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
/*
* Data
*/
private ObjectMapper objectMapper = new ObjectMapper();
/*
* Auth user
*/
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
try {
BufferedReader reader = request.getReader();
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
LoginCredentials authRequest = objectMapper.readValue(sb.toString(), LoginCredentials.class);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
authRequest.getUsername(), authRequest.getPassword()
);
setDetails(request, token);
return this.getAuthenticationManager().authenticate(token);
} catch (IOException e) {
throw new IllegalArgumentException(e.getMessage());
}
}
}
package com.revo.ToDoList.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import com.revo.ToDoList.filter.JwtAuthorizationFilter;
import com.revo.ToDoList.filter.MyAuthenticationFilter;
import com.revo.ToDoList.handler.MyAuthenticationSuccessHandler;
import com.revo.ToDoList.service.UserService;
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
/*
* Data
*/
#Autowired
private UserService userService;
public static final String secret = "ACAB SKURWYSYNY";
public static final long expirationTime=86400000;
/*
* Http Security Rules
*/
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/user/register").permitAll()
.anyRequest().authenticated().and()
.addFilterBefore(authFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JwtAuthorizationFilter(super.authenticationManagerBean(), userService), BasicAuthenticationFilter.class)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.exceptionHandling()
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
http.cors().disable().csrf().disable();
}
/*
* Auth Manager Configuration
*/
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
}
/*
* ENCODER
*/
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/*
* My Authentication Filter
*/
private MyAuthenticationFilter authFilter() throws Exception {
MyAuthenticationFilter authFilter = new MyAuthenticationFilter();
authFilter.setAuthenticationSuccessHandler(new MyAuthenticationSuccessHandler());
authFilter.setAuthenticationManager(super.authenticationManager());
authFilter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/login", "POST"));
return authFilter;
}
}
It looks like a CORS issue.
Probably you need to set cors.allowed.headers
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Origin, Accept, X-Requested-With, Content-Type, Content-Disposition, Access-Control-Request-Method, **Access-Control-Request-Headers**</param-value>
</init-param>
If is spring, it might be something like below:
#Override
protected void configure(HttpSecurity http) throws Exception {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedHeaders(List.of("Authorization", "Cache-Control", "Content-Type"));
........
.........
}
I got a similar problem once,
You may try adding below to your main class
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("http://localhost:8080");
}
};
}

CORS issue with JSON data

I'm getting the below CORS issue in my Angular 7 application when running locally.
Access to XMLHttpRequest at 'http://localhost:8080/OnlineOrganicMarket/api/changeorderstatus' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I'm using Jersey RESTful Web Services framework at the backend. This happens only with header type application/json. It is working for application/x-www-form-urlencoded.
I think there is a problem with my CORSFilter class.
package com.oom.services.filter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.annotation.Priority;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import org.glassfish.jersey.server.ExtendedUriInfo;
#Provider
#Priority(Priorities.HEADER_DECORATOR)
public class CORSFilter implements ContainerRequestFilter, ContainerResponseFilter {
private static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
private static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";
private static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods";
private static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
private static final String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers";
private static final String AUTHORIZATION = "authorization";
private static final String ORIGIN = "Origin";
private static String extractAllowedMethods(final ExtendedUriInfo extendedUriInfo) {
final Optional<Class<?>> optional = extendedUriInfo.getMatchedRuntimeResources().stream()
.flatMap(r -> r.getResources().stream()).flatMap(r -> r.getHandlerClasses().stream())
.filter(r -> r.getPackage().getName().startsWith("com.oom.services")).findFirst();
if (optional.isPresent()) {
return Arrays.stream(optional.get().getDeclaredMethods())//
.flatMap(m -> Arrays.stream(m.getAnnotations()))//
.map(a -> a.annotationType().getAnnotation(javax.ws.rs.HttpMethod.class))//
.filter(Objects::nonNull)//
.map(HttpMethod::value)//
.distinct()//
.collect(Collectors.joining(", "));
}
// Returning OPTIONS is a bit shady, as ACAM is about *real*, actual methods only.
return "OPTIONS";
}
#Context
private HttpServletRequest request;
#Context
private ExtendedUriInfo extendedUriInfo;
#Override
public void filter(final ContainerRequestContext requestContext) throws IOException {
final String origin = requestContext.getHeaderString(ORIGIN);
if (origin != null && "OPTIONS".equals(requestContext.getMethod())) {
request.setAttribute(this.getClass().getName(), true);
requestContext.abortWith(Response.ok("CORS OK, carry on.", MediaType.TEXT_PLAIN_TYPE).build());
}
}
/**
* #see https://www.w3.org/TR/cors/
* #see https://jmchung.github.io/blog/2013/08/11/cross-domain-on-jersey-restful-web-services/
* #see https://solutionsisee.wordpress.com/2016/06/30/adding-cors-support-in-jersey-server/
*/
#Override
public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext)
throws IOException {
final MultivaluedMap<String, Object> responseHeaders = responseContext.getHeaders();
final String origin = requestContext.getHeaderString(ORIGIN);
if (origin != null) {
// The presence of the Origin header marks a CORS request.
responseHeaders.add(ACCESS_CONTROL_ALLOW_ORIGIN, origin);
responseHeaders.add(ACCESS_CONTROL_ALLOW_METHODS, extractAllowedMethods(extendedUriInfo));
responseHeaders.add(ACCESS_CONTROL_ALLOW_HEADERS, AUTHORIZATION + ", X-Requested-With, Content-Type");
if (requestContext.getHeaderString(ACCESS_CONTROL_REQUEST_HEADERS) != null) {
responseHeaders.add(ACCESS_CONTROL_ALLOW_CREDENTIALS, requestContext
.getHeaderString(ACCESS_CONTROL_REQUEST_HEADERS).toLowerCase().contains(AUTHORIZATION));
}
}
if (request.getAttribute(this.getClass().getName()) != null) {
// We are in a CORS Preflight answer, fast tracked. The entity (== response body) is not
// relevant.
}
}
}
My service part where I'm having issue
#POST
#Path("/changeorderstatus")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response updateOrderStatus(OrderBean orderStatus) {
JSONArray responseJson = new OrderDAO().updateOrderStatus(orderStatus);
return Response.ok(responseJson, MediaType.APPLICATION_JSON).header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS").build();
}
I tried disabling CORS through some extensions and disabling it in the chrome browser. Nothing worked.
As commented by #mamounothman, I tried out the below code from Paul Samsotha's answer
It started working when I added Content-type key in the Access-Control-Allow-Headers
Originally answered by Paul Samsotha
package com.oom.services.filter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.annotation.Priority;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import org.glassfish.jersey.server.ExtendedUriInfo;
#Provider
#PreMatching
public class CORSFilter implements ContainerRequestFilter, ContainerResponseFilter {
/**
* Method for ContainerRequestFilter.
*/
#Override
public void filter(ContainerRequestContext request) throws IOException {
// If it's a preflight request, we abort the request with
// a 200 status, and the CORS headers are added in the
// response filter method below.
if (isPreflightRequest(request)) {
request.abortWith(Response.ok().build());
return;
}
}
/**
* A preflight request is an OPTIONS request
* with an Origin header.
*/
private static boolean isPreflightRequest(ContainerRequestContext request) {
return request.getHeaderString("Origin") != null
&& request.getMethod().equalsIgnoreCase("OPTIONS");
}
/**
* Method for ContainerResponseFilter.
*/
#Override
public void filter(ContainerRequestContext request, ContainerResponseContext response)
throws IOException {
// if there is no Origin header, then it is not a
// cross origin request. We don't do anything.
if (request.getHeaderString("Origin") == null) {
return;
}
// If it is a preflight request, then we add all
// the CORS headers here.
if (isPreflightRequest(request)) {
response.getHeaders().add("Access-Control-Allow-Credentials", "true");
response.getHeaders().add("Access-Control-Allow-Methods",
"GET, POST, PUT, DELETE, OPTIONS, HEAD");
response.getHeaders().add("Access-Control-Allow-Headers",
// Whatever other non-standard/safe headers (see list above)
// you want the client to be able to send to the server,
// put it in this list. And remove the ones you don't want.
"X-Requested-With, Authorization, " +
"Accept-Version, Content-type, Content-MD5, CSRF-Token");
}
// Cross origin requests can be either simple requests
// or preflight request. We need to add this header
// to both type of requests. Only preflight requests
// need the previously added headers.
response.getHeaders().add("Access-Control-Allow-Origin", "*");
}
}
Still I'm not getting why the previous code I was using did not work with the header type Content-Type - application/json even though it had the header type Content-Type in the Access-Control-Allow-Header's list.

How can to send request from RestyGWT part to another server project?

I have restyGWT+GXT project, that send request to server project (Spring Boot), so, my restyGWT+GXT part:
buiid.gradle:
...
compile 'org.fusesource.restygwt:restygwt:2.0.3'
compile 'javax.ws.rs:jsr311-api:1.1.1'
my rest service in restyGWT+GXT part:
import org.fusesource.restygwt.client.MethodCallback;
import org.fusesource.restygwt.client.RestService;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.List;
public interface LoadHelloService extends RestService {
#GET
#Path("/rest/loadHelloService")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public void loadHelloService(MethodCallback<List<Hello>> callback);
}
bean Hello.java:
public class Hello {
private final String id;
private final String name;
#JsonCreator
public Hello(#JsonProperty("id") String id, #JsonProperty("name") String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
}
in MainMenuPage (implements IsWidget):
on click menuButton1 send request to server project (Spring Boot):
#UiHandler("menuButton1")
void selectOnMenu1(SelectEvent event) {
...
restServerLoader.loadHelloListFromServer();
}
so, RestServerLoader class with method loadHelloListFromServer:
import com.google.gwt.core.client.GWT;
import com.sencha.gxt.widget.core.client.box.MessageBox;
import org.fusesource.restygwt.client.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class RestServerLoader {
public void loadHelloListFromServer() {
String pageBaseUrl = "http://127.0.0.1:8080/";
Defaults.setServiceRoot(pageBaseUrl);
Map<String, String> headers = new HashMap<>();
headers.put("Access-Control-Allow-Methods", "GET");
Resource resource = new Resource(Defaults.getServiceRoot(), headers);
LoadHelloService service = GWT.create(LoadHelloService.class);
((RestServiceProxy)service).setResource(resource);
service.loadHelloService(new MethodCallback<List<Hello>>() {
public void onSuccess(Method method, List<Hello> response) {
MessageBox messageBox = new MessageBox("response (list) = " + response.toString());
messageBox.show();
//code your stuff here
}
public void onFailure(Method method, Throwable exception) {
MessageBox messageBox = new MessageBox("exception = " + exception);
messageBox.show();
//code your stuff here
}
});
}
}
So, and when I send request loadHelloService I have: org.fusesource.restygwt.client.FailedStatusCodeException: status code 0.
:(((((((
my server part (Spring Boot) rest:
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.List;
#Path("/")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public class HelloResource {
#Context
private HttpServletResponse response;
#OPTIONS
#Path("loadHelloService") //The response for the preflight request made implicitly by the bowser
public Response loadHelloPreflight() {
Response response = Response.ok()
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "POST, GET, UPDATE, OPTIONS")
.header("Access-Control-Allow-Headers", "*")
.header("Access-Control-Max-Age", "18000").build();
return response;
}
#GET
#Path("loadHelloService")
public List<Hello> loadHelloList() {
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "POST, GET, UPDATE, OPTIONS");
response.addHeader("Access-Control-Allow-Headers", "*");
List<Hello> list = new ArrayList<>();
list.add(new Hello("1", "ronan"));
list.add(new Hello("2", "john"));
return list;
}
}
so, When I send request, I input method loadHelloPreflight, but when send request to loadHelloList I have: org.fusesource.restygwt.client.FailedStatusCodeException: status code 0., Why??? :((, When I send request to server part (Spring Boot) from browser Postman Client - all good!, I get list of hellos, but I want do it from restyGWT+GXT part :((( Help me, please.
Did you forget some cors headers like below ?
.header("Access-Control-Allow-Headers", "x-http-method-override");

CookieParam in RESTEasy Singleton

I'm injecting my cookie param in that way (using javax.ws.rs.CookieParam)
#CookieParam("parameterCookie")
private String parameterCookie;
i have a problem to inject that parameter using Resteasy
ERROR
It is illegal to inject a #CookieParam into a singleton
That is a BaseResource and i can't modify all resources to accept that paramenter on all methods (it costs a lot). How could i inject that CookieParam in Resteasy without modify all resources?
You can work around this by injecting HttpHeaders instead:
import org.jboss.resteasy.core.Dispatcher;
import org.jboss.resteasy.mock.MockDispatcherFactory;
import org.jboss.resteasy.mock.MockHttpRequest;
import org.jboss.resteasy.mock.MockHttpResponse;
import org.junit.Before;
import org.junit.Test;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
public class CookieTest {
static final String COOKIE_NAME = "parameterCookie";
Dispatcher dispatcher;
#Before
public void setUp() throws Exception {
dispatcher = MockDispatcherFactory.createDispatcher();
dispatcher.getRegistry().addSingletonResource(new Resource());
}
#Test
public void name_StateUnderTest_ExpectedBehavior() throws Exception {
String cookieValue = String.valueOf(System.currentTimeMillis());
MockHttpResponse response = new MockHttpResponse();
MockHttpRequest request = MockHttpRequest.get("/")
.cookie(COOKIE_NAME, cookieValue);
dispatcher.invoke(request, response);
assertThat(response.getContentAsString(), is(COOKIE_NAME + "=" + cookieValue));
}
#Path("/")
public static class Resource {
#Context HttpHeaders headers;
#GET #Path("/")
public String getCookie(){
return headers.getCookies().get(COOKIE_NAME).toString();
}
}
}

Categories