简体   繁体   中英

Spring Boot: Customize API response based on the User Roles

I want to apply some Authorizations logic on my controller's Methods I have an endpoint named Interview that has findInterviewById(id) method which returns an Interview object.

The application holds different users [ Owner , Recruiters , Candidate and Guest ]

Each one can get access to the findInterviewById(id) to read the Interview object and createInterview(Interview) method to create the interview but each one must read or write the object with restrict mode depending on his Role

Example

  • Recruiter : can read the entire interview object returned by the findInterviewById(id)
  • Guest : should read only some fields in the interview object returned by the findInterviewById(id)

The same thing for createInterview(Interview) method, Recruiter can touch all the fields of interview, but Candidate can touch some field

Some solutions said you could duplicate the endpoints but it's not best practice for a big application

How can i implement this certain authorization logic to achiche this behaviour

You might use @JsonSerialize and implement the required JSON response based on the authority of a user using serialize(Interview interview, JsonGenerator jgen, SerializerProvider provider)

Example

Consider the UserDTO class which is responsible for displaying the list of users. You have to use @JsonSerialize(using = CustomSerializer.class) at the class level of your DTO or domain.

DTO/Modal

@JsonSerialize(using = UserDTOSerializer.class)
public class UserDTO {

    private Long id;

    @NotBlank
    @Pattern(regexp = Constants.LOGIN_REGEX)
    @Size(min = 1, max = 50)
    private String login;

    @Size(max = 50)
    private String firstName;

    @Size(max = 50)
    private String lastName;

    @Email
    @Size(min = 5, max = 254)
    private String email;

    @Size(max = 256)
    private String imageUrl;

    private boolean activated = false;

    //getter-setters and constructors
}

Custom Serializer

Now let's implement the custom serializer by @Override the serialize() method, inside it you may get the authority from the security context and customize the response as follows

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.learning.jhipster.security.AuthoritiesConstants;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
public class UserDTOSerializer extends StdSerializer<UserDTO> {

    public UserDTOSerializer() {
        this(null);
    }

    public UserDTOSerializer(Class<UserDTO> t) {
        super(t);
    }

    @Override
    public void serialize(UserDTO user, JsonGenerator jgen, SerializerProvider provider) throws IOException {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        jgen.writeStartObject();
        if(authentication.getAuthorities().toString().contains(AuthoritiesConstants.ADMIN)) {
            jgen.writeNumberField("id", user.getId());
            jgen.writeStringField("login", user.getLogin());
            jgen.writeBooleanField("activated", user.isActivated());
            jgen.writeStringField("imageUrl", user.getImageUrl());
        }
        jgen.writeStringField("firstName", user.getFirstName());
        jgen.writeStringField("lastName", user.getLastName());
        jgen.writeStringField("email", user.getEmail());
        jgen.writeEndObject();
    }
}

Response

User logged in as ROLE_USER authority will get the following response

[
    {
        "firstName": "User",
        "lastName": "User",
        "email": "user@localhost"
    }
]

User logged in as ROLE_ADMIN will get the following response

[
    {
        "id": 1,
        "login": "system",
        "activated": true,
        "imageUrl": "",
        "firstName": "System",
        "lastName": "System",
        "email": "system@localhost"
    }
]

You can use anonymous feature of c# and return only specific property based on role. For example

If (role == "Guest")
var condidate = new { Id = 1, FirstName = "James", LastName = 
"Bond", location = "noida", skill = ".net" };

else if (role == "Recruiter")
var condidate = new { Id = 1, FirstName = "James", LastName = 
"Bond", location = "noida", skill = ".net", salary = "11LPA",         
expectSalary= "15LPA"};

you can write in your business logic. Above could in API methods findInterviewById() or CreateInterview()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM