Authentication to access Spring boot Zuul Service routes
Asked Answered
H

1

7

I have configured my micro services using Spring boot zuul and eureka services. Now I need to authenticate all routes/REST API calls. I mean, for all APIs client send one accessToken. On zuul service, before routing to the particular service, I have to call a micro service (auth-service) with accessToken and that auth-service will check the user exists or not for the accessToken sent. If the accessToken is valid then only routing should happen.

Please help me to implement this using spring boot service.

Thanks.

Hercegovina answered 4/8, 2017 at 15:47 Comment(3)
Isn't your accessToken a signed token you can trust?Rollo
spring-security is the way to do this properly. You should only do this at all if you know that there's no way a caller can just go around your proxy and hit the microservice directly.Atwater
@Andy Brown, can you please provide in detail or some link to check ?Hercegovina
B
7

You need to write a filter. A zuul pre filter is what you need. You can access your auth server within the filter and if the token is invalid you don't call your microservice and return a response immediately. If it is valid you let the request go down to micro services.

An example filter class:

public class AuthFilter extends ZuulFilter {

    @Autowired
    RestTemplate restTemplate;

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        //get your token from request context and send it to auth service via rest template
        boolean validToken = restTemplate.exchange(or getForObject or other methods of restTemplate which you find suitable for method and return type of your auth service controller method)
        if(!validToken) {
            ctx.setSendZuulResponse(false); //This makes request not forwarding to micro services
            ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
            ValidationResponse validationResponse = new ValidationResponse();
            validationResponse.setSuccess(false);
            validationResponse.setMessage("Invalid Access...");
            ObjectMapper mapper = new ObjectMapper();
            String responseBody = mapper.writeValueAsString(validationResponse);
            ctx.setResponseBody(validationResponse);
            ctx.getResponse().setContentType("application/json");
            //If you want to do any thing else like logging etc, you can do it.
        }
        return null;
    }

}
Brame answered 8/8, 2017 at 13:52 Comment(7)
Thanks for your response. I can able to set response as string. ctx.setResponseBody("Invalid Access ...!"); I need to set Response Body as custom object like ValidationResponse. ValidationResponse is my unique response object for all services. Something like below: validationResponse.setSuccess(false); validationResponse.setMessage("Invalid Access..."); And then set this validationResponse as response object. Can you please help with that ??Hercegovina
@Krishna, No problem, you only need to set requestContext responseBody. I updated the answer.(I set content type to json. If you use xml, you can set content type accordingly)Brame
No, com.netflix.zuul.context.RequestContext.setResponseBody() is supporting only String data type.Hercegovina
@Krishna Sorry, I forgat to say you need to convert your object. I am adding right away. I used com.fasterxml.jackson.databind.ObjectMapper in my project. You can use another if you want. The trick here is the setting content type and convert your object accordinglyBrame
Thanks. Its working for application/json as expected. But not working for application/xml. Below is the checking: String responseBody = mapper.writeValueAsString(validationResponse); ctx.setResponseBody(responseBody); if(request.getContentType().equalsIgnoreCase("application/json")){ ctx.getResponse().setContentType("application/json"); } if(request.getContentType().equalsIgnoreCase("application/xml")){ ctx.getResponse().setContentType("application/xml"); } it always giving json string. Please tell me how to handle for xml ??Hercegovina
@Krishna You have to use XmlMapper for converting. XmlMapper.writeValueAsString(yourObject) You may need to add dependency for XmlMapper. <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.7.4</version> </dependency>Brame
XmlMapper not worked for me. I used JAXBContext instead and working fine with it. Thank you so much for your help to achieve this.Hercegovina

© 2022 - 2024 — McMap. All rights reserved.