I have a question to ask regarding conversion of an Entity to DTO. I have read that it is good to convert the Entity to DTO in rest application so that it hides your entity data.
For e.g
If i have an entity User and there are two rest endpoints - GET and PUT. GET fetches the data and PUT updates the data. Now if i do not convert the Entity into DTO i would expose my Entity instances and someone could use the instance with PUT method and update the User Data.
But my question is this thing can also happen if i am using the same DTO class to convert the data while using the GET and PUT method (which most developers do). So how does conversion of entity to DTO increase security.
User.java
#Entity
#Table
public class User{
private int id;
private int name;
private String password;
}
Please give you valuable comments to clarify this doubt of mine. Thanks!
You explicitly define which attributes are available to your application's peripherals. I'm not sure this increases security, but it protects you from unwanted behavior. If you automatically convert your REST bodies to JSON via Jackson, every getter of your entity would be exposed. Hence if you add a getXXX method to evaluate something in your domain, you could unwillingly expose this to the outside world.
For instance you might not want to expose which authorizations are available for your user, or the user's password.
I like to use the Adapter Pattern for REST/JMS interaction.
Separation of concerns.
GET: In your example you would not return id back to the client would you?
PUT: You would not populate the id.
Related
Im making a api with spring, in which I return an array of objects, each of them contains name and an array. The problem is that it doesn't return the Id of each object which I store in jpa repository. The question is how do I turn Id visible in response
#Column
private #Id #GeneratedValue Long id;
private String QuestionName;
Good evening,
Some more information about how you are structuring your project should be in order.
However, I am going to assume your code snippet is from a class using the #Entity annotation.
If so, you require a Class noted with #RestController, where a #PostMapping function would be defined where you would receive your information from the client (Possibly in a JSON format, which can be directly converted into a Map by the application). By using a function with a return format of ResponseEntity, you can return HTTP messages to the client. In this return statement, you may return whatever you please, meaning you may return a JSON back to the client in question.
Personally, I recommend creating a QuestionDTO class (Data Transfer Object), in order to not send the Object with all Server-Side information to the client-side, easing creation of client-side code too!
I know this was a lot to take in, I leave some sources down here:
Response Entities and how they work
Building REST applications with Spring Boot
I hope this was of use, hit me up if you need further assistance,
Have a good one!
Add getter and setter methods for id field and then try.
In my application written in Hibernate and Spring MVC I've got simple classes representing Customer, his main office Address and list of Locations of rest of his offices. There is a form that allows to add and edit data of Customer, then Spring MVC maps it to DTO, validates, sends down to Service which converts it to (slightly different) Entity and saves.
I thought about using value objects for representing and implicit validation for some objects - i.e. PhoneNumber, Address, but I don't really know how to use them in these frameworks - even if I think I understand the Value Object concept and immutability.
If I will use them in DTOs used in presentation layer then I can't rely on Spring mechanism of mapping fields from form to object - because there are no setters. And I must do the mapping manually in Controller or Service.
Should I use Value Objects in Entity (embed them)? Or maybe this is too simple case to use Value Objects at all?
Your question is not primarily about value objects, but your main concern (if I understand correctly) is how to send data from a web form, validate the data and save the data in entities.
Create a form object such as MyForm with all fields that the user can enter in your screen. The form object serves to transport your data to the server, for example:
class MyForm {
#NotBlank
private String name;
#NotBlank
private String phoneNumber;
#NotBlank
private String address;
// getters and setters
}
On the server side controller validate, convert and store the data:
#Controller
class GuestbookController {
#RequestMapping(value = "/guestbook", method = RequestMethod.GET)
String myget(Model model, MyForm form) {
// put data on model
}
#RequestMapping(value = "/mysubmit", method = RequestMethod.POST)
String mysubmit(#Valid MyForm form, Errors errors, Model model) {
if (errors.hasErrors()) {
return myget(model, form);
}
myrepository.save(new MyEntity(form.getName(), form.getPhoneNumber(), form.getAddress()));
return "redirect:/myview";
}
}
You probably need more details about the address than what fits in a single String. Then, yes, using a value object containing all the address details is fine.
here is my humble response.
DTOs are simple data containers with no logic,
and value objects are the opposite and encapsulate the logic.
Just a funny thing, DTOs were called value objects in the past in Java.
One way to see it (as I read it) is to let value objects encapsulate all the logic for entities, entities that handle only identity.
DTOs allow decoupling the domain model from the UI (or any other ports/adapters).
Should value objects be used outside the domain layer ? I don't know but personally I don't do it. In my setups, they are used by the application layer and inside the domain, but outside the application layer there is only DTOs.
I have DTOs that Spring can handle and data mappers to do the translation (dto to model at the UI/app layers border). The DTOs generally can have setters (event public property according to some people).
Now, if you want to use immutable object mapped by the framework, the solution depends on the technology you are using. When I do webservices with JSON (and Jackson), I map immutable commands object directly with #JsonCreator annotation on constructor but I couple my pojos to jackson. To avoid this, you can also add your customer serializers to the framework to let it convert automatically the data structure around controller method parameters.
Otherwise, you always can do mapping with data mapper or factory methods. (I believe you wrote a post about that...)
It is a rather general question, but I will give a stripped down example. Say I have a Web CRUD application that manages simple entities stored in a database, nothing but classic : JSP view, RequestMapping annotated controller, transactional service layer and DAO.
On an update, I need to know the previous values of my fields, because a business rule asks a for a test involving the old and new values.
So I am searching for a best practice on that use case.
I thing that spring code is way more extensively tested and more robust than my own, and I would like to do it the spring way as much as possible.
Here is what I have tried :
1/ load an empty object in controller and manage the update in service :
Data.java:
class Data {
int id; // primary key
String name;
// ... other fields, getters, and setters omitted for brevity
}
DataController
...
#RequestMapping("/data/edit/{id}", method=RequestMethod.GET)
public String edit(#PathVariable("id") int id, Model model) {
model.setAttribute("data", service.getData(id);
return "/data/edit";
}
#RequestMapping("/data/edit/{id}", method=RequestMethod.POST)
public String update(#PathVariable("id") int id, #ModelAttribute Data data, BindingResult result) {
// binding result tests omitted ..
service.update(id, data)
return "redirect:/data/show";
}
DataService
#Transactional
public void update(int id, Data form) {
Data data = dataDao.find(id);
// ok I have old values in data and new values in form -> do tests stuff ...
// and MANUALLY copy fields from form to data
data.setName(form.getName);
...
}
It works fine, but in real case, if I have many domain objects and many fields in each, it is quite easy to forget one ... when spring WebDataBinder has done it including validation in the controller without I have to write any single thing other than #ModelAttribute !
2/ I tried to preload the Data from the database by declaring a Converter
DataConverter
public class DataConverter<String, Data> {
Data convert(String strid) {
return dataService.getId(Integer.valueOf(strid));
}
}
Absolutely magic ! The data if fully initialized from database and fields present in form are properly updated. But ... no way to get the previous values ...
So my question is : what could be the way to use spring DataBinder magic and to have access to previous values of my domain objects ?
You have already found the possible choices so i will just add some ideas here ;)
I will start with your option of using a empty bean and copying the values over to a loaded instance:
As you have shown in your example it's an easy approach. It's quite easily adaptable to create a generalized solution.
You do not need to copy the properties manually! Take a look at the 'BeanWrapperImpl' class. This spring object allows you to copy properties and is in fact the one used by Spring itself to achieve it's magic. It's used by the 'ParameterResolvers' for example.
So copying properties is the easy part. Clone the loaded object, fill the loaded object and compare them somehow.
If you have one service or just several this is the way to go.
In my case we needed this feature on each entity. Using Hibernate we have the issue that an entity might not only change inside a specific service call, but theoretically all over the place..
So I decided to create a 'MappedSuperClass' which all entities need to extend. This entity has a 'PostLoad' event listener which clones the entity in a transient field directly after loading. (This works if you don't have to load thousands of entities in a request.) Then you need also the 'PostPersist' and 'PostUpdate' listeners to clone the new state again as you probably don't reload the entity before another modification.
To facilitate the controller mapping I have implemented a 'StringToEntityConverter' doing exactly what you did, just generalized to support any entity type.
Finding the changes in a generalized approach will involve quite a bit of reflection. It's not that hard and I don't have the code available right now, but you can also use the 'BeanWrapper' for that:
Create a wrapper for both objects. Get all 'PropertyDescriptors' and compare the results. The hardest part is to find out when to stop. Compare only the first level or do you need deep comparison?
One other solution could also be to rely on Hibernate Envers. This would work if you do not need the changes during the same transaction. As Envers tracks the changes during a flush and creates a 'Revision' you can "simply" fetch twp revisions and compare them.
In all scenarios you will have to write a comparison code. I'm not aware of a library but probably there is something around in the java world :)
Hope that helps a bit.
I have a graph of domain objects and i need to build a DTO to send it to the view. How to design it properly? I see 2 options where can I put the DTO building code:
1) Into the DTO constructor. But then the domain object has to present all fields to DTO via getters so it's not a DDD.
public DTO(DomainObject domain) {
/// access internal fields of different domain object.
}
2) Into the domain object. There will be no problem with accessing fields but the domain object will grow very fast when new view are added.
public DTO1 createDTO1() {
...
}
public DTO2 createDTO1() {
...
}
// and so on...
How should I build DTOs properly?
I think there is a bigger issue at play here. You should not be querying your domain. Your domain should be focused on behaviour and, as such, will quite possibly not contain the data in a format suitable for a view, especially for display purposes.
If you are sending back your entire, say, Customer object to Edit then you are performing entity-based interactions that are very much data focused. You may want to try and place more attention on task-based interactions.
So to get data to your view I'd suggest a simple query layer. Quite often you will need some denormalized data to improve query performance and that will not be present in your domain anyway. If you do need DTOs then map them directly from your data source. If you can get away with a more generic data container structure then that is first prize.
Variants:
Constructor with simple types in DTO: public DTO(Long id, String title, int year, double price)
Separate class - converter with methods like: DTO1 createDTO1(DomainObject domain)
Framework for copy properties from one object to other, like Dozer: http://dozer.sourceforge.net/
1) ... the domain object has to present all fields to DTO via getters ...
2) ... the domain object will grow very fast ...
As you can see, the problem is that both alternatives are coupling your model with your DTOs, so you need to decouple them: introduce a layer between them in charge of performing the mapping/translation.
You may find this SO question useful.
domain object has to present all fields to DTO via getters so it's not
a DDD
Just because a domain object has getters doesn't make it anemic or anti-DDD. You can have getters and behavior.
Besides, since you want to publish to the View a DTO containing particular data, I can't see how this data can remain private inside the domain object. You have to expose it somehow.
Solution 2) breaks separation of concerns and layering (it's not a domain object's business to create a DTO) so I'd stick with 1) or one of #pasha701's alternatives.
I'm attempting to integrate Spring Security with ACL support into an existing GWT application, and if I click another unhelpful link I swear will need a new mouse and keyboard. I've worked through what will be needed to use Spring to authenticate against Active Directory via LDAP, and I've worked out how we can assign custom permissions based on AD attributes (i.e. group membership), and I've even worked out how to perform a custom check against permissions (a true bitmask operation) using a custom ACL schema. What I haven't figured out is just what goes into the ACL tables.
ACL_SID
id:bigint (pk)
principal:boolean (ak)
sid:varchar (ak)
This table is pretty self-explanatory; we'll be using non-principal entries here only.
ACL_CLASS
id:bigint (pk)
class:varchar (ak)
This table is also pretty self-explanatory. As I understand it, we simply create an entry for every class/interface we wish to secure.
ACL_ENTRY
id:bigint (pk)
acl_object_identity:bigint (fak)
ace_order:int (ak)
sid:bigint (fk)
mask:bigint
granting:boolean
audit_success:boolean
audit_failure:boolean
This table is also mostly self-explanatory; we've customized the schema with a bigint/long in the mask field, but the question stems from just what acl_object_identity is referencing. Obviously, it points to the field in ACL_OBJECT_IDENTITY, but...
ACL_OBJECT_IDENTITY
id:bigint (pk)
object_id_class:bigint (fak)
object_id_identity:bigint (ak)
parent_object_identity:bigint (fk)
owner_sid:bigint (fk)
entries_inheriting:boolean
The object_id_identity is, what? A method? How is it referenced by way of Spring Security's annotations?
MyClass.java
#PreAuthorize("hasPermission(#someInput, 'READ')")
public boolean myMethod(String someInput) {
return true;
}
Presumably, #someInput refers somehow to the ACL_OBJECT_IDENTITY.object_id_identity field, but how?
First you need some kind of domain object class to store your data. This class must have a getId() method. For example:
public class DomainObject {
private Long id;
private String data;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
Change your secured method to:
#PreAuthorize("hasPermission(#someInput, 'READ')")
public boolean myMethod(DomainObject someInput) {
return true;
}
Now, someInput.getId() is the same as ACL_OBJECT_IDENTITY.object_id_identity.
have a look at the Grails Spring Security ACL Plugin Documentation.
It explains the domain classes used for the specific plugin, but it might help you. Look for AclObjectIdentity and AbstractAclObjectIdentity.
The ACL_OBJECT_IDENTITY.object_id_identity field is the instance id and uniquely identify the instance (together with object_id_class)
In your example, 'someInput' would be that instance.
this piece of code is taken from the beforementioned documentation:
#PreAuthorize("hasPermission(#report, delete) or hasPermission(#report, admin)")
void deleteReport(Report report) {
report.delete()
}
It explains itself immo. The report is deleted if the currently authenticated user has permission 'admin' or 'delete' for the given Report instance. Report is someInput in your code snippet.
Hope this helps.
The question seems to suggest a slight misunderstanding of Spring ACL. In the question, we are asked how to register an ACL for a String object, so that this method protection will work:
#PreAuthorize("hasPermission(#someInput, 'READ')")
public boolean myMethod(String someInput) {
return true;
}
As mentioned in this answer, it doesn't really make sense to protect a String object. When you think about it, this makes sense. Loosely speaking, we can divide all objects into two categories:
Objects that are persisted to the DB - let's call them entities
Objects that are not persisted to the DB - let's call them transients
In any real-life use case I can think of, it only makes sense to protect access to an entity, not a transient; I'll argue for this case in general later. To start with though, let's stick with a use case related to that of the question to see why protection of a transient probably isn't what's desired in this case.
Use Case
It's not 100% clear what the use case is in the question e.g. what someInput represents. But I'm assuming the use case is similar to the following. Suppose there are BankAccount entities and some operation on those entities e.g. readAccount. Only users who have read access to a BankAccount should be allowed to call readAccount. Now, BankAccount entities may be uniquely identifiable by their accountNumber, which is of type String. So we may be mistakenly led to try something like this, which is similar to the code in the question:
#PreAuthorize("hasPermission(#accountNumber, 'READ')")
public Account readAccount(String accountNumber) {
//CODE THAT RETRIEVES THE ENTITY FROM THE DB AND RETURNS IT
}
OK, it's not a bad assumption to make. I suppose the idea in our minds at this stage is that Spring ACL stores a table of account numbers, and for each account number, a list of people who have READ access to it. The problem is, Spring ACL doesn't work like that. As mentioned in this answer, Spring ACL identifies an objects in the following way:
What is the class of the object? In this case, it would be java.lang.String
What is the ID of the object? In this case, Spring ACL requires that the object needs a getId() method. Luckily, if you're using Hibernate, all your entities will have this by default, so you don't need to do anything extra to implement it. But what about String? Well, this doesn't have a getId() method. So Spring ACL won't be able to register an ACL for it and you won't be able to set up any permissions for Strings.
When you think about it, it actually makes sense that Spring ACL is designed this way. The getId() method allows us to associate the persisted ACL permissions entries with the persisted entities. This is the typical use case. So in the above example, what we're really trying to do is restrict access to Account objects, not account numbers. In that case, we have two options: preauthorize or postuathorize.
With pre-authorize, we'd need the fully-qualified path to the Account class. So let's say it's in the package X.Y, we'd have:
#PreAuthorize("hasPermission(#accountId, 'X.Y.Account', 'READ')")
public Account readAccount(Long accountId) {
//CODE THAT RETRIEVES THE ENTITY FROM THE DB AND RETURNS IT
}
Notice that in the above, we are using the ID, not the account number, to identify the account. This is the only way you are allowed identify an entity with Spring ACL, because the getId() is the link between the ACLs and their associated objects. Of course, you're free to write whatever code you like to retrieve the object by the given ID e.g. you could do something silly like increment the ID before retrieving it. So the object returned isn't guaranteed to be the same one that's authorized in this case: that's up to you to write the correct retrieval code.
The other way we can protect the method is with post authorize, as follows:
#PostAuthorize("hasPermission(returnObject, 'READ')")
public Account readAccount(String accountNumber) {
//CODE THAT RETRIEVES THE ENTITY FROM THE DB AND RETURNS IT
}
In this case, the code that retrieves the account entity is actually called, and then only after it's retrieved, the account, which is the object returned, is checked by the ACL framework against the current user and the READ permission. An advantage here is that we can retrieve the account any way we like e.g. by accountNumber in this case. Another advantage is that the object that's authorized is guaranteed to be the same as the one returned. The disadvantage is that we have to actually do the retrieval before we can make the call as to whether the user has permission or not. And if they don't have permission, then the retrieved object is effectively thrown away and so it may be a bit less performant than #PreAuthorize if the retrieval code is expensive to run.
Why Protecting Strings with Spring ACL Doesn't Make Sense Anyway
Technically speaking, I suppose you might be able to protect Strings, or indeed any other transient as long as it has a getId() method. With Strings, we could maybe add an extension function getId() for example. But I can't think of a practical use case for why we'd want to do that. For example, imagine we not only have Account objects but we also have Customer objects. And let's say Customer objects are uniquely identifiable by a customerNumber field, which is a String. And suppose we want to restrict access to customers in a similar way to accounts. Then what if coincidentally a customerNumber matched an accountNumber? In Spring ACL, we are only allowed one entry in the object identity table for every combination of object class plus ID, as per the Spring docs:
CONSTRAINT uk_acl_object_identity UNIQUE (object_id_class, object_id_identity)
So, suppose the String "fadfads389" happens to be both a customerNumber for some Customer and an accountNumber for some Account. If we were to restrict access to it via Spring ACL, what would that mean? Would it mean that a user has access to the account? The customer? Both?
Hopefully this example demonstrates why it doesn't really make sense to protect some transient class such as String with Spring ACL when that transient is used to identify entities: when we're interested in protecting entities we just protect the entities themselves, using the implicit ID of those entities e.g. the ID stored by Hibernate.
Transients Could Still be protected
Of course, there's nothing stopping you from adding object identity entries into the Spring ACL acl_object_identity table for any class you want, as long as that class has a getId() method. So it is certainly possible for you to add permissions relating to transients, and should those transients appear again in memory then Spring ACL will kick in. But this isn't really what Spring ACL was designed for - it's really meant to protect entities, not transients, which are linked to the ACL logic by getId().
Strings Could Still be Used in PreAuthorize
Now, although we shouldn't really use Spring ACL to protect Strings, that's not to say that #PreAuthorize is completely off the table when it comes to Strings. We note that #PreAuthorize can handle any SpEL expression, the same for #PostAuthorize and the other method annotations as pointed out here. So, for example, you would be able to do something like this:
#PreAuthorize("#user.accountNumbers.contains(#accountNumber)")
public Account readAccount(String accountNumber, User user) {
//CODE THAT RETRIEVES THE ENTITY FROM THE DB AND RETURNS IT
}
The above assumes that the User class maintains a list of account numbers to which that user has access, so presumably a User is an entity, or at least is backed by some DB-persisted data.
However, beware if you do want to go down this path. Not only do you risk entangling your access control logic with the rest of your business logic, you also might lose out on the performance front; Spring ACL uses caching to make permissions lookups fast whereas the above code presumably needs to fetch User data from the DB in order to do the authorization.