I need to add some audit logs to some business methods that are not in the web tier. One of the requirements are to store in this audit logs the user that executed the business method and the IP of the remote terminal. I decided to use AspectJ to Audit all this methods to avoid contaminating them with no bussiness code. (Note: I'm not using Spring, this is an old Struts 1 webapp)
public void myMethod(Object param, HttpRequest request**){
//Bussiness code that never use request param
}
#After("bla bla matches myMethod")
public void myAdvice(JoinPoint jp){
Object request = (HttpServletRequest)jp.getArgs()[1];
//bla bla using the request to get user and IP
}
So my question is, does anyone have any suggestion to obtain in a better or elegant way the Servlet Request in the Advice? In fact, myMethod does not contain Audit code (that is really good) but now have a second parammeter that is not used directly by the method and can become confusing to other developers. Please do not recomend me to advice the Servlet instead the business method.
Logging the IP from myMethod already ties the method to the web tier (or at least a tier with a meaningful IP address). An HttpServletRequest isn't appropriate, obviously, but an implementation providing "useful" information about the context of the call would be.
If the goal is to remove any extra parameter to myMethod, my first thought would be to create a RequestProcessor that stores the "useful" info in a ThreadLocal, which would be used by the logging aspect.
Related
just another question about the correct usage of HttpClient, because unless i am missing something, I find contradicting information about HttpClient in Microsoft Docs. These two links are the source of my confusion:
https://learn.microsoft.com/en-us/azure/architecture/antipatterns/improper-instantiation/#how-to-fix-the-problem
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-3.1#typed-clients
First one states that the best approach is a shared singleton HttpClient instance, the second that the AddHttpClient<TypedClient>() registers the service as transient, and more specifically (copied from that URL):
The typed client is registered as transient with DI. In the preceding
code, AddHttpClient registers GitHubService as a transient service.
This registration uses a factory method to:
Create an instance of HttpClient.
Create an instance of GitHubService, passing in the instance of HttpClient to its constructor.
I was always using AddHttpClient<TypedClient>() and feeling safe, but now i am puzzled again... And making things worse, I found this github issue comment by #rynowak which states:
If you are building a library that you plan to distribute, I would
strongly suggest that you don't take a dependency on
IHttpClientFactory at all, and have your consumers pass in an
HttpClient instance.
Why this is important to me? Because, I am in a process of creating a library that mainly does two things:
Retrieve an access token from a token service (IdentityServer4)
Use that token to access a protected resource
And I am following the typed clients approach described in the link 2 above:
//from https://github.com/georgekosmidis/IdentityServer4.Contrib.HttpClientService/blob/master/src/IdentityServer4.Contrib.HttpClientService/Extensions/ServiceCollectionExtensions.cs
services.AddHttpClient<IIdentityServerHttpClient, IdentityServerHttpClient>()
.SetHandlerLifetime(TimeSpan.FromMinutes(5));
Any advises or examples of how a concrete implementation based on HttpClient looks like, will be very welcome.
Thank you!
This is a more general Spring question that isn't necessarily a Spring Social Facebook issue; however, I'm asking the question here because it is not clear to me how Spring is managing the Facebook reference that is passed into the controller constructor.
I'm running this in a Spring boot app, version 1.5.3.RELEASE.
I've googled around and have read many things about how scoped-proxies work and whether the Controller is a singleton and such; but something is still not clear to me with this particular use case. My concern is over whether or not two or more simultaneous request will cause one reference to interfere with the other. It seems to me that there will be a conflict regardless of the scoped-proxy solution. To address this concern, I injected a Facebook and ConnectionRepository object into the controller constructor wrapped in a Provider class.
#Inject
public CopyGroupController(
Provider<Facebook> facebook,
Provider<ConnectionRepository> connectionRepository) {
It appears to have injected meaningful data; but when attempting to run this code:
#PostConstruct
public void init() {
ConnectionRepository repo = connectionRepository.get();
this.userManager.createOrGetUser(
repo.findPrimaryConnection(Facebook.class));
}
This failure occurs:
java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
This creates more uncertainty because I thought the FacebookTemplate was being managed as a request or session scoped bean and that it would Inject as a Provider so the object would reside on ThreadLocale; so two or more concurrent requests will not conflict. Passing a request scoped bean in a controller singleton constructor doesn't make any sense to me either. So I'm puzzled as to why a user specific reference would even be passed into a constructor that should only be called once.
I've tried setting breakpoints in the constructor to verify whether or not there is a conflict; but The same error as above would occur. Could someone please explain to me whether or not this is an issue and if so; how is the best, most modern way to resolve it.
Any assistance would be greatly appreciated.
Thank you in advance.
You have to register a RequestContextListener
Here you can find the problem detail
And here you can get how to add in using spring boot
so i want to create some service that accesses external API, and i want to cache common requests from the API inside of that service, it depends on 3 other services, but i want to give it its own instance of cache, MemoryDistributedCache might later be changed for something else
services.AddSingleton<ISomeApi, SomeApi>(provider => new SomeApi(
Configuration.Get<Options>(),
new MemoryDistributedCache(new MemoryCache(new MemoryCacheOptions())),
provider.GetService<ILogger<SomeApi>>()
));
now from my Controllers i can access the api via DI, it works nicely but im not sure if its some sort of an anti-pattern or if there are better ways of doing it
i mean the real problem is separating the internal cache, requesting
IDistributedMemory from one service would give me the same object as if i request it from another service, they must be separated
This sounds like something you could use a proxy or decorator pattern for. The basic problem is that you have a service that does some data access, and another service responsible for caching the results of the first service. I realize you're not using a repository per se, but nonetheless the CachedRepository pattern should work for your needs. See here:
http://ardalis.com/introducing-the-cachedrepository-pattern
and
http://ardalis.com/building-a-cachedrepository-via-strategy-pattern
You can write your cached implementation such that it takes in the actual SomeApi type in its constructor if you don't need that part of the design to be flexible.
Spring Security can be a nightmare for the new user. Nothing is solid, everything can be configured by some #Autowired bean or other, there are a million options, and seemingly simple things become very complex very quickly.
<End of Rant>
Now then, I have the following requirements and setup for a corporate intranet application:
1) I am trying to avoid the use of security.xml and configure everything with java annotations.
2) There is a central corporate cookie-based authentication service which authenticates the user as someone entitled to use the corporate intranet. Usernames and Passwords are handled there, the application does not concern itself with them. There is a wealth of other information there, most of which my application doesn't need. The one absolute essential there is the userid entered by the user and validated by the service. This goes into the Principal and also is available as session data. This service is supplied as a servlet filter.
3) This filter includes a configuration option through which an adaptor can be attached, to perform other tasks, such as getting the authenticated user's application-specific roles from an application-maintained database. I am using such an adaptor for this task, which adds the roles from the database to an object that winds up in the Session attributes in some structure. By the end of this filter's and adaptor's execution the user's application-specific roles are in the session data.
4) I have added a class derived from com.att.voicetone.cwing.security.AbstractSecurityWebApplicationInitializer and in its beforeSpringSecurityFilterChain() method, have registered this filter from step 2 (which includes the adaptor from step 3) so that it is done first. All the above is working as I want it to work.
5) Now, I am looking at how all this may be tied into Spring Security. My goal is to be able to use something like this:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/index.html","/transcripts.html").hasRole("MY_APP_USER");
http.authorizeRequests()
.antMatchers("/assign.html","/report.html").hasRole("MY_APP_ADMIN");
http.authorizeRequests()
.antMatchers("/", "/x/**", "/audio/**").hasRole("MY_APP_USER");
http.authorizeRequests()
.antMatchers("/oam/**").hasRole("MY_APP_ADMIN");
}
It seems as though what I must do is implement a class that extends org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter, and insert it into the filter chain and somehow code it to translate the role information into a format that the hasRole() calls above will find the information they are looking for.
But this is the point, after all the "hard" work has seemingly been done, where I run into countless ConfigurationBuilders, AuthenticationManagers, AuthenticationTokens, etc., all of which have many customization opportunities, none of which seem to fit with the "simple" task I feel is waiting for me, somewhere, in the morass of configurable options, that I haven't been able to find through hours of starting at code, javadocs, etc.
If you've followed me thus far, what is the sweet spot I am missing for translating the roles from the above session object so that SpringSecurity can handle them with the hasRole() code?
Or to put it another way, where is hasRole() looking and what does it expect to find there?
The answer to this question is that you do the "translation" in a AuthenticationDetailsSource, which creates the UserDetails object which has the collection of GrantedAuthorities. That is the piece that I was missing.
However, I'm still not out of the woods. On to my next SO question ...
I have a login.java servlet and, as its name says, it provides login facilities to my web application.
I'm a newbie and I'm using EJB 3.1 and EE 6. In my LoginBean.java EBJ I have a no-arguments constructor and another one that has some parameters (email, password, etc).
At certain point in the servlet code I have the calling to instantiate my EJB:
#EJB LoginBean loginBean;
I'd like to know if it's possible (and how) to call the other constructor instead of the zero-arguments one.
Thanks a lot.
Cheers.
You don't want to do that. The one and same servlet is shared among all users, so the EJB is also shared among all users. You don't want to store user-specific data as instance variable of the servlet or EJB class. It would be shared among all webpage visitors.
Rather move the arguments to a EJB method which you invoke in the doPost() method of the login servlet.
User user = loginBean.login(username, password);
and then store this in the HTTP session when it went successful
request.getSession().setAttribute("user", user);
so that the rest of your webapp can intercept on this to determine if the user is logged in or not.
if (request.getSession().getAttribute("user") != null) {
// User is logged in.
} else {
// User is not logged in.
}
I 100% agree with BalusC. In addition to his answer I would like to add that you normally* never explicitly reference the constructor of an EJB bean, even if doing so would theoretically make sense (e.g. when passing in some dependencies, or some configuration parameter).
EJB beans are managed objects and what you are getting in your #EJB annotated field is not the actual object but a stub (proxy). The actual object instance to which the stub points is most likely constructed long before you get this stub to it and also very likely comes from a pool.
(*)Some kind of units tests may be an exception to this rule.