All
I have created a simple service using CXF Simple Frontend by referring to official document at
http://cxf.apache.org/docs/simple-frontend.html
I'm just wondering how I can access the HttpServletRequest in the method of service implementation class HelloWorldImpl in the example of the above link.
Any help would be appreciated.
Best Regards
I guess, you can try something like:
PhaseInterceptorChain.getCurrentMessage().get("...");
To find the exact key cotaining the request use - PhaseInterceptorChain.getCurrentMessage().keySet();. It should contain someting like Http Request.
Hope this helps.
Cheers!
You can use: org.apache.cxf.jaxrs.ext.MessageContext class to retrieve the HttpServletRequest. In your implementation add:
#Context
private MessageContext context;
HttpServletRequest request = context.getHttpServletRequest();
And you will get the request.
#Resource
WebServiceContext wsContext;
#Context
private HttpServletRequest request;
private HttpServletRequest getRequest() {
MessageContext mc = wsContext.getMessageContext();
HttpServletRequest req;
if (mc != null) {
req = (HttpServletRequest) mc.get(MessageContext.SERVLET_REQUEST);
} else {
req = request;
}
return req;
}
Related
I am trying to integrate Twilio to my AngularJS and spring MVC application. After following Twilio documentation I set up at front end device setup and calling etc. In Java class I am generating a token, and passing that token while making the call. In java the code is:
#RequestMapping(value = "/phoneCalling", method {
RequestMethod.GET, RequestMethod.POST
})
public #ResponseBody Phone phoneCalling(HttpServletRequest request, HttpServletResponse response, #RequestParam String leadPhone) {
try {
Number number = new Number.Builder(leadPhone).build();
Dial dial = new Dial.Builder().number(number).build();
VoiceResponse responseVR = new VoiceResponse.Builder().dial(dial).build();
System.out.println(responseVR.toXml());
} catch (TwiMLException e) {
e.printStackTrace();
}
return null;
}
At twilio TwiML, I set request URL as:
https://865c048b.ngrok.io/ZingyCRM/phoneCalling/
As I am testing locally, so used ngrok. But after clicking on make a call, it gives me voice message as application error occurred. I believe the TwiML request URL I might be setting wrong, can some one help here?
I have been trying to set up a CXF endpoint in Camel, using spring java config like so:
#Bean
public CxfEndpoint anEndpoint() {
CxfEndpoint endpoint = new CxfEndpoint();
endpoint.setAddress(getEndpointUrl());
endpoint.setServiceClass(ServiceSOAP.class);
endpoint.setWsdlURL("/wsdl/ServiceSOAP.wsdl");
String httpProxyHost = httpProxyHost();
String httpProxyPort = httpProxyPort();
Map<String, Object> properties = new HashMap<>();
properties.put("https.proxyHost", httpProxyHost());
properties.put("https.proxyPort", httpProxyPort());
properties.put("http.proxyHost", httpProxyHost());
properties.put("http.proxyPort", httpProxyPort());
endpoint.setProperties(properties);
return endpoint;
}
However, this is not working on either http or https endpoint urls.
I have also tried setting these properties on CamelContext directly with the same result.
The route is working fine in the environment with a direct connection to the internet, e.g., locally, but not where it is deployed behind an http proxy.
We're using apache camel 2.15.2 and apache cxf 3.1.0. Any help is greatly appreciated!
The resolution turned out to be simple if tortuous to figure out. One has to use a CxfEndpointConfigurator to set up HTTPConduit properties like so:
#Bean
public CxfEndpoint anEndpoint() {
CxfEndpoint endpoint = new CxfEndpoint();
endpoint.setAddress(getEndpointUrl());
endpoint.setServiceClass(ServiceSOAP.class);
endpoint.setWsdlURL("/wsdl/ServiceSOAP.wsdl");
endpoint.setCxfEndpointConfigurer(anEndpointClientConfigurer());
return endpoint;
}
private CxfEndpointConfigurer anEndpointClientConfigurer() {
return new CxfEndpointConfigurer() {
#Override
public void configure(AbstractWSDLBasedEndpointFactory factoryBean) {
}
#Override
public void configureClient(Client client) {
HTTPConduit conduit = (HTTPConduit) client.getConduit();
HTTPClientPolicy policy = new HTTPClientPolicy();
policy.setProxyServer(httpProxyHost());
policy.setProxyServerPort(httpProxyPort());
conduit.setClient(policy);
}
}
References: 1 and 2
I'm following a Udemy course in attempt to build my first Spring Boot application. Rather than using Spring Security, they are using JJWT to implement stateless authentication.
The front end is in Angular, and because it runs on it's own server, CORS is used to open everything up so that the Angular app can hit the Java backend API.
I'm worried that this will open the door to CSRF or other security holes.
After some digging I found similar code to what the Udemy course is using here, but I don't know enough about security to know if it's enough.
The code in question is as follows:
Filter:
public class JwtFilter extends GenericFilterBean {
#Override
public void doFilter(final ServletRequest req,
final ServletResponse res,
final FilterChain chain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) req;
final String authHeader = request.getHeader("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
throw new ServletException("Missing or invalid Authorization header.");
}
final String token = authHeader.substring(7); // The part after "Bearer "
try {
final Claims claims = Jwts.parser().setSigningKey("secretkey")
.parseClaimsJws(token).getBody();
request.setAttribute("claims", claims);
}
catch (final SignatureException e) {
throw new ServletException("Invalid token.");
}
chain.doFilter(req, res);
}
Cors Config:
#Configuration
public class CorsConfig {
#Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true); //usually want this
config.addAllowedOrigin("*");//not sure if secure?
config.addAllowedHeader("*");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
Filter added to main application class:
#SpringBootApplication
public class BackendApplication {
#Bean
public FilterRegistrationBean jwtFilter() {
final FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter((Filter) new JwtFilter());
registrationBean.addUrlPatterns("/rest/*");
return registrationBean;
}
public static void main(String[] args) {
SpringApplication.run(BackendApplication.class, args);
}
}
So is this sort of setup secure enough to be used in production code, or is a more robust solution needed?
Or is there a better way entirely to do stateless authentication? If they were both running on the same domain I wouldn't need CORS right?
Do not use JWT for security purposes. JWT contains information other than random keys which should not be present in the authorisation header. Although we can sign a JWT token, yet we should avoid it. Instead save the extra information in the database and query it whenever you receive the token at server side to check authenticity of the token. Also, the algorithm type none can prove to be a security disaster if exploited by an attacker. Use simple random string as token. Fairly simple and more secure. Confidential information resides in database and not in the token and we all know that databases are very secure.
I am using spring 4 + hibernate 4 + spring security (RESTFull Webservice API) and angular at front. (Very new to this all).
My failure handler is as follows:
#Component
public class AuthFailure extends SimpleUrlAuthenticationFailureHandler {
#Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
}
If my request fails I get 401 response which is as expected. Now I want to add AccountLocked and CredentialsExpiredException functionality. I am setting "false" appropriately when I return "User". Again I do get response with status as 401.
return new User(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, AuthorityUtils.NO_AUTHORITIES);
As I always get 401 and I do not get any user object inside response(Or may be don't know how to get it), at front end I am unable to find whether it's due to bad credentials or account locked or credentials expired as I want to redirect to another page. I also tried to catch exceptions and tried to forward different statuses but does not seems to hit this code. I always get 401.
#ExceptionHandler(LockedException.class)
#ResponseStatus(value = HttpStatus.BAD_REQUEST)
public ModelAndView handleLockedException(Exception e) {
logger.error("Exception occurred => " + e.getMessage());
return new ErrorResponse(HttpStatus.BAD_REQUEST.value(), e.getMessage(), "Spring security exception").asModelAndView();
}
Please help me - how shall I handle at angular end so that I can redirect to appropriate page?
I think solution was very simple, just did not pay attention to AuthFailure method parameters. Modified my AuthFailuar as follows:
#Component
public class AuthFailure extends SimpleUrlAuthenticationFailureHandler {
#Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
if (exception instanceof LockedException) {
response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED);
}else if {
....
} else {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
}
}
Now as I have given different status codes I can easily differentiate at the front. Hope for somebody this would be helpful.
I have a route that defines a CXFRS endpoint. I need to retrieve custom HTTP header values from the inbound request...
from(CXF_RS_ENDPOINT_URI)
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
Message inMessage = exchange.getIn();
System.out.println("headers->" + inMessage.getHeaders());
...
here is my unit test code to simulate a client request...
HttpGet get = new HttpGet("http://localhost:9000/rest/customerservice/customers/126");
get.addHeader("myHeader", "1234");
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(get);
The problem is that the custom header "myHeader" is unavailable from my route. Is there another way to get to it?
From looking at the camel-cxf source code, I can see that the default header strategy/binding logic only sets up predefined HTTP headers. Is there a reason why other headers aren't passed through as well?
Either way, what is the best approach to override this behavior?
thanks
After more investigating, this was found to be a bug in CAMEL-CXF. It has been fixed to support custom headers in the Camel trunk (slated for 2.5 release)...