Spring - Provide parsed JWT as Resource method parameter - spring

In Spring framework, is there a way to parse JWT and provide it's data as one of the Resource method parameters?
Something like this:
class MyJwtToken {
String fieldA;
Integer fieldB;
}
public ResponseEntity<> create(
#JwtToken MyJwtToken token,
#RequestBody Item item
) {
item.setFieldA(token.getFieldA());
persist(item);
return ...;
}

Related

Reactive Spring Security PostAuthorize annotation doesn't work

Using Webflux and Reactive Spring Security, how do you do post processing via annotations to control access to methods?
Trying a very basic sample, I'm not able to get the value from the PostAuthorize annotation. For example
#GetMapping
#PostAuthorize("#email == authentication.principal.email")
public Flux<Project> sampleTest(final String email) {
log.info("email: {}", email);
return Flux.empty();
}
The email will always be null. I have the basic wiring working to the fact if I set something like #PreAuthorize("hasRole('ADMIN')") I'll get back a 403.
I can extract the Authentication out with a helper like:
public Mono<Authentication> getAuthentication() {
return ReactiveSecurityContextHolder.getContext()
.map(SecurityContext::getAuthentication)
.flatMap(Mono::just);
}
I may not be understanding your question correctly, but the PostAuthorize uses the return object - the body of the method doesn't have access to anything in the SPEL expression.
Something like this might work -
#GetMapping
#PostAuthorize("returnObject == someCondition")
public Flux<Project> sampleTest(final String email) {
// get some data and return it
}
But maybe you want to filter the items in the Flux?
You might look at the #PostFilter annotation -
// assuming there's an email property on your Project object.
#GetMapping
#PostFilter("filterObject.getEmail() == authentication.principal.email")
public Flux<Project> sampleTest() {
// get some data and return it
}

Name alias in mapping query parameters to object in Spring

I have a class
class Request {
private String ftr;
// more properties
}
And a method in controller class
#GetMapping
public String list(#Valid Request request) {
//...
}
When I send a request to the method the url is https://example.com?ftr=sms
Is it possible to have an alias to a query parameter like in the class
class Request {
#QueryParameter(name="ftr")
private String filter;
// ...
}
And to map same request url to this class?
You can just annotate your request parameter by #RequestParam(name = "ftr") like below:
#GetMapping
public String list(#RequestParam(name = "ftr") #Valid String filter, ...) {
//...
}
but you can't do it to pass an Object like you did, so you need to pass each field as a parameter, or you can use a map to encapsulate all your parameters like this:
#GetMapping
public String list(#RequestParam Map<String, String> params) {
//...
}
and this is a list of all request annotations that you can use with your methods:
RequestParam : used for get params
PathVariable : used for path params
RequestHeader : used for headers params
RequestBody : used for post/put/patch/... body

Spring MVC parse web url Object

I have a GET request in the format below
http://www.example.com/companies?filters=%7B%22q%22%3A%22aaa%22%7D
After decode it is
filters={"q":"aaa"}
I have created an Object named Filters as below
public class Filters {
private String q;
//getter setter....
}
and in my controller
#RequestMapping(method = RequestMethod.GET)
public List<CompanyDTO> getCompanies(Filters filters) {
filters.getQ();
//do things
}
However, the filters.getQ() is null.
Am I doing something incorrect here?
You need to associate the request parameter to the method argument. Add #RequestParam to your method i.e.
#RequestMapping(method = RequestMethod.GET)
public List<CompanyDTO> getCompanies(#RequestParam(value="filters") Filters filters) {
filters.getQ();
//do things
}
Instead of #RequestParam, use #RequestBody
Instead of String filters=%7B%22q%22%3A%22aaa%22%7D, pass JSON object as parameter http://www.example.com/companies?filters={"q":"aaa"}

Using custom JSON serialization for Spring WebSocket #MessageMapping/#SubscribeMapping

This works fine
In my Spring-based application, I have set up a HTTP-based REST endpoint. This endpoint "speaks" JSON:
#Controller
public class HttpRestController implements RestController {
#Override
#RequestMapping(value = "/users/{user}", method = RequestMethod.GET)
#ResponseBody
public getUser(#PathVariable User user) {
User jsonFriendlyUser = new JacksonAnnotatedUser(user);
return jsonFriendlyUser;
}
}
As these JSON payloads have to follow unusual naming conventions, I used annotations such as #JsonRootName and #JsonProperty to customize the serialized property names:
#JsonRootName("uussaaar")
public class JacksonAnnotatedUser implements User {
//...
public int getId() {
return id;
}
#JsonProperty("naammee")
public String getName() {
return name;
}
#JsonSerialize(using = FriendsJsonSerializer.class )
public Set<User> getFriends() {
return friends;
}
#JsonIgnore
public String getUnimportantProperty() {
return unimportantProperty;
}
}
With this custom JSON metadata, querying /users/123 via HTTP returns the following JSON payload:
{"uussaaar":
{
"id":123,
"naammee":"Charlie",
"friends": [456, 789]
}
}
The following doesn't work as expected
Now I am playing around with Spring's WebSocket support: I want to create a STOMP-based REST endpoint. Therefore i created a StompRestController like this:
#Controller
public class StompRestController implements RestController {
#Override
#SubscribeMapping("/users/{user}")
public getUser(#DestinationVariable User user) { // assuming this conversion works
User jsonFriendlyUser = new JacksonAnnotatedUser(user);
return jsonFriendlyUser;
}
I would have expected for #SubscribeMapping/#MessageMapping to follow the same JSON serialization behavior as #RequestMapping. But this is not the case. Instead, when querying this WebSocket/STOMP endpoint, #SubscribeMapping/#MessageMapping-annotated methods will result in sending a STOMP message to clients with a payload/body corresponding to the "normal" Jackson serialization rules, e.g.
{
"id":123,
"name":"Charlie"
"friends":[{argh recursion}, ...],
"unimportantProperty":"This property shall not be part of JSON serialization"
}
Therefore:
How can I have #SubscribeMapping/#MessageMapping-annotated methods obey custom #JsonXXX annotations for returned values?
Is there another way aside #JsonXXXfor doing such returned value serialization?

Return custom object AND controlling response code in JAX-RS

I'm using JAX-RS in my web application to return my own object.
I want to keep doing it, but I want to set the HTTP response code (e.g. 401 for unauthorized, etc.).
From the information I've found it seems like I have to return the type Response and not my custom object.
Is that correct?
My current code (simplified) - when MyReponse is an object that Jaxb knows how to deal with:
#POST
#Produces({MediaType.APPLICATION_XML , MediaType.APPLICATION_JSON})
public MyResponse RegisterUser (
#FormParam("userName") String userName,
#FormParam("password") String password) {
// add user logic
return new MyResponse(....<params to ctor...);
}
Yes, you are right.
You'll need to use something like:
#POST
#Produces({MediaType.APPLICATION_XML , MediaType.APPLICATION_JSON})
public Response RegisterUser (
#FormParam("userName") String userName,
#FormParam("password") String password) {
// add user logic
return Response.status(401).entity(new MyResponse(...)).build();
}
see http://jersey.java.net/nonav/documentation/latest/jax-rs.html#d4e355 (and other chapters) for additional useful information.
You can extend Response class and return your custom status when you override getStatus() method.

Resources