Secondary save method in a Spring Data JPA repo? - spring-security

I have a Spring Data JPA repo exported via Spring Data REST and secured with Spring Security. I also need to save data to this table from an unsecured endpoint but my save() method is secured.
I cannot create a second repository because of https://jira.spring.io/browse/DATAREST-923.
The only way I know of is manipulating the security context by hand every time before calling the secured save() method.
Is there a better way?

If you secured only save method you can try to use insecurely saveAndFlush method.
Another approach - customize your repo. First - implement the custom repo, for example:
public interface CustomRepo {
MyEntity saveUnsecured(MyEntity entity);
}
#Repository
public class CustomRepoImpl implements CustomRepo {
private final EntityManager em;
public CustomRepoImpl(EntityManager em) {
this.em = em;
}
#Transactional
#Override
public MyEntity saveUnsecured(MyEntity entity) {
if (entity.getId() == null) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
}
Then extend your repo from custom one:
public interface MyEntityRepo extends JpaRepository<MyEntity, Long>, CustomRepo {
//...
}

Related

How to access token additionalInformation to validate expression-based access control

I succesfully added user_id additionnal information on the generated tokens on the authorization server side by implementing a TokenEnhancer. Here is a token generated:
{"access_token":"ccae1713-00d4-49c2-adbf-e699c525d53e","token_type":"bearer","expires_in":31512,"scope":"end-user","user_id":2}
Now, on the Resource server side, which is a completely separate spring project communicating through a RemoteTokenServices, i would like to use theses informations with method expression-based access control. For example i would like to use the added user_id data (it is Spring Data JPA repository for use with Spring Data Rest):
#PreAuthorize("#oauth2.hasScope('admin') or #id == authentication.principal.user_id")
#Override
UserAccount findOne (#P("id") Integer id);
The #oauth2.hasScope('admin') works as expected but the #id == authentication.principal.user_id" part obviously not.
how can i access to the additional data added to the token on expression-based access control ?
So i've found myself. The key interface is UserAuthenticationConverter.
Using the default provided DefaultUserAuthenticationConverter class, we can set a UserDetailsService which is used to set authentication.principal with the UserDetail object returned by the UserDetailsService. Without that, authentication.principal is only set with the token username as a String.
Here is an extract of my ResourceServerConfigAdapter:
#Configuration
#EnableResourceServer
protected static class ResourceServerConfiguration
extends ResourceServerConfigurerAdapter {
#Bean
UserDetailsService userDetailsService () {
return new UserDetailsServiceImpl();
}
#Bean
public UserAuthenticationConverter userAuthenticationConverter () {
DefaultUserAuthenticationConverter duac
= new DefaultUserAuthenticationConverter();
duac.setUserDetailsService(userDetailsService());
return duac;
}
#Bean
public AccessTokenConverter accessTokenConverter() {
DefaultAccessTokenConverter datc
= new DefaultAccessTokenConverter();
datc.setUserTokenConverter(userAuthenticationConverter());
return datc;
}
#Bean
RemoteTokenServices getRemoteTokenServices () {
RemoteTokenServices rts = new RemoteTokenServices();
rts.setCheckTokenEndpointUrl(
"http://localhost:15574/oauth/check_token");
rts.setAccessTokenConverter(accessTokenConverter());
rts.setClientId("client");
rts.setClientSecret("pass");
return rts;
}
...
}
Another method is to override the DefaultUserAuthenticationManager and provide a custom public Authentication extractAuthentication(Map<String, ?> map).
Once this is done, we can use the user data on expression-based access control like that:
#PreAuthorize("#oauth2.hasScope('admin') or #id == authentication.principal.userAccount.id")
#Override
UserAccount findOne (#P("id") Integer id);
Note that userAccount is my original DOMAIN user object. It could be everything the UserDetailsService returns.
EDIT:
To answer to Valentin Despa, here is my UserDetailsService implementation:
#Component
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
UserAccountRepository userAccountRepository;
public UserDetails loadUserByUsername (String username)
throws UsernameNotFoundException {
// Fetch user from repository
UserAccount ua = this.userAccountRepository
.findByEmail(username);
// If nothing throws Exception
if (ua == null) {
throw new UsernameNotFoundException(
"No user found having this username");
}
// Convert it to a UserDetails object
return new UserDetailsImpl(ua);
}
}

Null reference on Dagger 2 #Inject

I've created a gist highlighting the issue I'm running into. I'm using an Application Module to provide a Firebase dependency for me to inject elsewhere.
When I try to #Inject Firebase mFirebase in the data layer that dependency is never satisfied.
I'm trying to keep the Context out of my other layers, but the Firebase service depends on it. I'm interested in learning any other patterns to help keep Android classes out of my business logic.
FirebaseService.java
public class FirebaseService {
#Inject Firebase mFirebaseRef; //NEVER GET'S INJECTED!
#Override
public LoginResult signinWithEmail(final String email, final String password) {
mFirebaseRef.dostuff(); //THIS REFERENCE DOESN'T GET INJECTED!
}
}
ApplicationModule
#Provides
#Singleton
Firebase provideFirebase(#ApplicationContext Context context) {
Firebase.setAndroidContext(context);
return new Firebase(Util.FIREBASE_URL);
}
ApplicationComponent
#Singleton
#Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
#ApplicationContext Context context();
Application application();
Firebase firebase();
}
MyActivity
public class MyActivity extends AppCompatActivity {
private ActivityComponent mActivityComponent;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public ActivityComponent getActivityComponent() {
if (mActivityComponent == null) {
mActivityComponent = DaggerActivityComponent.builder()
.activityModule(new ActivityModule(this))
.applicationComponent(MyApplication.get(this).getComponent())
.build();
}
return mActivityComponent;
}
The full code example is on github
Annotating a field with #Inject is not enough for the field injection to work. There's no magic involved, you just have to tell Dagger to do the injection.
First, add this method to your ApplicationComponent:
void inject(FirebaseService firebaseService);
Then, call this method from your FirebaseService (I guess it's an Android service, so add this to the onCreate method):
applicationComponent.inject(this);
This should do the trick. There's a great answer to a similar problem here.
EDIT
I've looked at your repository and I think you don't even need field injection in this case. You can just provide the Firebase dependency through a constructor. Here's your #Provides method:
#Provides
#Singleton
LoginService provideLoginService() {
return new FirebaseLoginService();
}
Add Firebase as a parameter to it and pass it to the FirebaseLoginService constructor:
#Provides
#Singleton
LoginService provideLoginService(Firebase firebase) {
return new FirebaseLoginService(firebase);
}
The constructor:
public FirebaseLoginService(Firebase firebase) {
this.mFirebaseRef = firebase;
}
Remove the #Inject annotation from your mFirebaseRef field since it's not needed anymore.
Here's the corresponding pull request.

How to use JSF ListDataModel object in abstract JPA criteria query

I'm Developing a JSF application using JPA 2 EclipseLink. I need to use a ListDataModel implementation of my list instead of the normal List implemettaion. I want to put this method in an abstract facade class so that it is available through the whole application. For a normal List implementation the abstract class
public List<T> findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
The abstract class implementation is:
#Stateless
public class ExportFacade extends AbstractFacade<Export> {
#PersistenceContext(unitName = "GazpromModulePU")
private EntityManager em;
#Override
protected EntityManager getEntityManager() {
return em;
}
public ExportFacade() {
super(Export.class);
}
This results from the method above are being correctly displayed and everything works fine. Now I want to do exactly the same thing but return the results in a ListDataModel. I tried:
public ListDataModel<T> findAllListDataModel() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return new ListDataModel<T>(getEntityManager().createQuery(cq).getResultList());
}
Using the same implementation (and the above abstract method), the list is not displayed and the error console is blank.I can manually hardcode the ListDataModel using a method like this:
public ListDataModel<Export> hardCodedMethod() {
if(someList == null) {
someList = makeModel();
}
return someList;
}
public ListDataModel<Export> makeModel() {
List<Export> elist = myFacade.findAll();
ListDataModel<Export> model = new ListDataMOdel<Export>(eList);
return model;
}
I would like to implement the above code in an abstract class instead of hardcoding it throughout the application. Would appreciate any guidance at all . Thanks in advance!
You're in first place not supposed to have any JSF artifact in a service class. This tight-couples your business tier to the current web tier. In other words, your business tier is not reusable across different web tiers, such as RESTful, Websockets, plain JSP/Servlet, etc.
Don't change your service class. Keep returning List from it. Make sure that you don't have any import javax.faces.*** line in any service class. Solve your problem in the JSF side instead. E.g. create an abstract backing bean.
public abstract class ListDataModelBacking<T> {
private transient ListDataModel<T> model;
public abstract List<T> getListFromService();
public ListDataModel<T> getModel() {
if (model == null) {
model = new ListDataModel<>(getListFromService());
}
return model;
}
}
Note that the DataModel implementations are supposed to be not serializable.
Then you can use it as below in a regular backing bean:
#Named
#ViewScoped
public class FooBacking extends ListDataModelBacking<Foo> implements Serializable {
#Inject
private FooService fooService;
#Override
public List<Foo> getListFromService() {
return fooService.listAll();
}
}
<h:dataTable value="#{fooBacking.model}" ...>
Alternatively, punch the ListDataModel and look for a simpler solution to the concrete functional requirement you tried to solve with having a ListDataModel property in bean. Perhaps EL 2.2 capability of passing method arguments? See also a.o. How can I pass selected row to commandLink inside dataTable?

How to use AOP on spring integration gateways?

I would like to intercept all spring integration gateways via AOP.
Is it possible to do that? If not what might be best way to do log input object coming to gateway?
#ContextConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
#DirtiesContext
public class AdviceExample {
#Autowired
private TestGateway testGateway;
#Test
public void testIt() {
System.out.println(this.testGateway.testIt("foo"));
}
#MessagingGateway
public interface TestGateway {
#Gateway(requestChannel = "testChannel")
#CustomAnnotation
String testIt(String payload);
}
#Configuration
#EnableIntegration
#IntegrationComponentScan
#EnableMessageHistory
#EnableAspectJAutoProxy
public static class ContextConfiguration {
LoggingHandler logger = new LoggingHandler(LoggingHandler.Level.INFO.name());
#Bean
public IntegrationFlow testFlow() {
return IntegrationFlows.from("testChannel")
.transform("payload.toUpperCase()")
.channel("testChannel")
.transform("payload.concat(' Manoj')")
.channel("testChannel")
.handle(logger)
.get();
}
#Bean
public GatewayAdvice gtwyAdvice(){
return new GatewayAdvice();
}
}
#Retention(value = RetentionPolicy.RUNTIME)
#Target(value = ElementType.METHOD)
#Inherited
public #interface CustomAnnotation{
}
#Aspect
public static class GatewayAdvice {
#Before("execution(* advice.AdviceExample.TestGateway.testIt(*))")
public void beforeAdvice() {
System.out.println("Before advice called...");
}
#Before("#annotation(advice.AdviceExample.CustomAnnotation)")
public void beforeAnnotationAdvice() {
System.out.println("Before annotation advice called...");
}
}
}
Yes, you can do that. Take a look to the standard Spring AOP Framework. Since all those #Gateway are beans in the end you can add for them any Advice by their bean names and for the specific method, if that. For example we often suggest to use #Transactional on gateway's methods. And this is exactly a sample "how to use AOP on integration gateway".

ASP.Net MVC 3 - unitOfWork.Commit() not saving anything

I created a web application using ASP.Net MVC 3 and EF 4.1, and I am using the UnitOfWork pattern, but nothing is getting committed to the database. All this is quite new to me, and I don't know where to start to resolve this issue.
I based myself on this post to create my web application:
http://weblogs.asp.net/shijuvarghese/archive/2011/01/06/developing-web-apps-using-asp-net-mvc-3-razor-and-ef-code-first-part-1.aspx
The final code, which can be obtained here also has a service layer and the UnitOfWOrk is being injected into the services.
Instead of using the custom injector based on Unity 2 as they are in that project, I am using Unity.Mvc3.
Here is my IUnitOfWork class:
public interface IUnitOfWork
{
void Commit();
}
And here is my UnitOfWork class:
public class UnitOfWork : IUnitOfWork
{
private readonly IDatabaseFactory databaseFactory;
private MyProjectContext dataContext;
public UnitOfWork(IDatabaseFactory databaseFactory)
{
this.databaseFactory = databaseFactory;
}
protected MyProjectContext DataContext
{
get { return dataContext ?? (dataContext = databaseFactory.Get()); }
}
public void Commit()
{
DataContext.Commit();
}
}
And here is how one of my service class look like:
public class RegionService : IRegionService
{
private readonly IRegionRepository regionRepository;
private readonly IUnitOfWork unitOfWork;
public RegionService(IRegionRepository regionRepository, IUnitOfWork unitOfWork)
{
this.regionRepository = regionRepository;
this.unitOfWork = unitOfWork;
}
...
}
At start-up, my UnitOfWork component is being registered like this:
container.RegisterType<IUnitOfWork, UnitOfWork>();
Now, no matter whether I try to insert, update or delete, no request is being sent to the database. What am my missing here?
UPDATE:
Here is the content of DataContext.Commit():
public class MyProjectContext : DbContext
{
public DbSet<Region> Regions { get; set; }
public virtual void Commit()
{
base.SaveChanges();
}
}
And here is databaseFactory.Get():
public interface IDatabaseFactory : IDisposable
{
MyProjectContext Get();
}
UPDATE #2:
Using the debugger, I am noticing that my Region service and controller constructors are getting called once when performing only a select, but they are called twice when performing an update. Is this normal?
Ok, I found the culprit. It has to do with how I was registering my database factory.
Instead of
container.RegisterType<IDatabaseFactory, DatabaseFactory>();
I needed
container.RegisterType<IDatabaseFactory, DatabaseFactory>(new HierarchicalLifetimeManager());
I found the information on this web site:
http://www.devtrends.co.uk/blog/introducing-the-unity.mvc3-nuget-package-to-reconcile-mvc3-unity-and-idisposable
That's an awfully complex implementation of Unit of Work. I actually prefer this one:
http://azurecoding.net/blogs/brownie/archive/2010/09/22/irepository-lt-t-gt-and-iunitofwork.aspx
Much simpler, and much more flexible. Although you do have to work out a few things for yourself.
May just be a typo but in UnitOfWork your private MyProjectContext is called dataContext (lowercase d)
But in your commit method your calling DataContext.Commit. Any chance that's actually calling a static method that you didn't intend to call? More likely a typo but thought I'd point it out.
+1 for an overly complex implementation of UnitOfWork.

Resources