I have a REST provider implemented using RestEasy. Currently the API uses method level security but we prefer URL-based security of Shiro. Our application uses CDI for dependency injection and it would be really great if currently logged in users can be injected into the beans since that would allow us to alter our responses based on user roles.
Are there any tutorials or examples that show how this can be done?
You can inject the SecurityContext to obtain the UserPrincipal:
#Context
private SecurityContext securityContext;
...
Principal principal = securityContext.getUserPrincipal();
If you need more information about the user you can use a CDI producer which fetches the User from e.g. a database:
public class UserProducer {
#Inject
private HttpServletRequest request;
#Produces
public User getUser() {
Principal principal = request.getUserPrincipal();
User user = db.fetchUser(principal.getName());
return user;
}
}
Then inject the User like this:
#Inject
private User user;
Related
I am currently using ABP and ocelot to build a api gateway for microservices. Everything works fine but now I want to use api gateway as a domain resolver. ABP's Domain Resolver works to resolve tenantid from different domains but i want ocelot to able to send the resolved tenant id to the downstream services(Include __tenant header in the headers of the request to the downstream service).
You can create a Middleware for adding ResolvedId to the request headers. So the ocelot will send the edited request to downstream with the tenantId.
Example:
public class MyMiddleware : IMiddleware, ITransientDependency
{
private readonly ICurrentTenant CurrentTenant;
public MyMiddleware(ICurrentTenant currentTenant)
{
CurrentTenant = currentTenant;
}
public Task InvokeAsync(HttpContext context, RequestDelegate next)
{
context.Request.Headers.Add("__tenant", CurrentTenant.Id.ToString());
return next(context);
}
}
As you see, the middleware manupilates the request, it's adding the CurrentTenantId to the request.
The CurrentTenant is found before by your "domain tenant resolver".
You can use this middleware between app.UseMultiTenancy() & app.UseOcelot()
...
app.UseMultiTenancy();
app.UseMiddleware<MyMiddleware>(); // it must be here, between them
app.UseOcelot();
...
I have SP initiated SAML 2.0 + SPRING boot application working behind the Load balancer. The load balancer end point (http://myserver.biz) is configured as entityBaseUrl for the application as
metadataGenerator.setEntityBaseURL(http://myserver.biz);
We added reverse proxy over the LB now which customer will be connecting to over internet. The proxy end point is https://myserverproxy.com. Now I configured entitybase url to something like
metadataGenerator.setEntityBaseURL(https://myserverproxy.com);
The trouble is internal customer will be using application url as http://myserver.biz while external customers coming over internet will use https://myserverproxy.com.
I am unable to configure two entityBaseUrls for the application, SAML MetadataGenerator class support only one entity base url at a time.
public class MetadataGenerator {
private String id;
private String entityId;
private String entityBaseURL;
...
}
How can this be achieved? Any solution on this?
#Bean
public MetadataGenerator metadataGenerator() {
MetadataGenerator metadataGenerator = new MetadataGenerator();
metadataGenerator.setEntityId(entityId);
metadataGenerator.setExtendedMetadata(extendedMetadata());
metadataGenerator.setIncludeDiscoveryExtension(false);
metadataGenerator.setKeyManager(keyManager());
metadataGenerator.setEntityBaseURL(entityBaseUrl);
return metadataGenerator;
}
I have a Spring MVC Server Backend with Rest-Services and an AngularJS WebFrontend.
i want to secure my spring mvc rest services but i want use java config.. and i have no idea how the configuration mus look like. Can someone help me with this ?
The only good implementation i have found is this : https://github.com/philipsorst/angular-rest-springsecurity
I use a postgrsDB and i wand store username and password and roles there, is the session token in the example from https://github.com/philipsorst/angular-rest-springsecurity only stored in cache and not in the db ?
At the moment i have a simple form login security, this was only for testing, but i did not use jsp i use only the spring mvc rest services and angularjs as webfrontend.. How can i modify my spring security code that it works with oauth2 like in the example from https://github.com/philipsorst/angular-rest-springsecurity ? I have at the moment only this two classes from spring security..
#Configuration
#EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("username").password("test").roles("User");
}
}
and then i register the securityConfig in my WebInitializer.
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[]{ PersistenceContext.class,AppConfig.class,SecurityConfig.class };
} ....
But the roles and username/password should stored in a database.. must i use a special databse schema for spring security to store username,password and roles in my db ?
And can i implement it so that i can only add the #Secured Annotation(or any other Annotation) over one of my rest services with the role in it ? Like #Secured("UserRole")
Or ist Basic Authentification easier ? can i secure my rest services with basic authentification with rolemanagement !? if so we can use basic authentification..
Best regards
In order to load users you have to create an authentication manager and wire a UserDetailsService into that authentication manager. The following doc link gives a good overview of authentication manager, and the core components associated.
http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#core-services
So, to answer your first question...
But the roles and username/password should stored in a database.. must i use a special
databse schema for spring security to store username,password and roles in my db ?
You can do either. If you want, spring security can handle all the database side for you, you just have to supply a reference to a JDBC datasource which has Spring's schema design.
http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#core-services-jdbc-user-service
and
http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#appendix-schema
-or-
You can utilize your own schema by providing a UserDetailsService implementation of your own that will load from your own database schema. Here's some samples that can get you started with that approach.
<context:component-scan base-package="com.example.security" />
<security:global-method-security secured-annotations="enabled" pre-post-annotations="enabled"/>
<bean id="dao-provider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"
p:userDetailsService-ref="myUserDetailsService"
p:passwordEncoder-ref="sha-pw-encoder"
p:saltSource-ref="my-salt-source" />
<bean id="sha-pw-encoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder"
p:encodeHashAsBase64="true" />
<bean id="my-salt-source" class="org.springframework.security.authentication.dao.ReflectionSaltSource"
p:userPropertyToUse="salt" />
<security:authentication-manager>
<security:authentication-provider ref="dao-provider"/>
</security:authentication-manager>
Finally, provide an implementation of the UserDetailsService like so:
#Component("myUserDetailsService")
public class MyUserDetailsServiceImpl implements UserDetailsService {
//Reference to the spring JPA repository for loading users
private final UserRepository userRepository;
#Autowired
public MyUserDetailsServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
#Override
#Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByName(username);
if (user != null) {
return new UserDetails() {
... //create the user details from the user object
}
} else {
String err = String.format("Failed to find username: %s in local database. Trying other auth mechanisms.", username);
throw new UsernameNotFoundException(err);
}
}
}
... for your second question:
And can i implement it so that i can only add the #Secured Annotation(or any other
Annotation) over one of my rest services with the role in it ? Like #Secured("UserRole")
Yes, the above configuration will allow you to use #Secured annotation by configuring the global-method-security.
And finally, yes all of this will still utilize basic authentication by default, but can be reconfigured to use digest authentication if necessary. I recommend giving a full read to the docs at http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/ in order to really grasp what you're trying to do. But, this should get you on your way.
I have the following sitebricks servlet. Foo.get() is accessible as a GET at /foo/bar. I deployed the servlet to GAE.
#Service
#At("/foo")
#Singleton
public class Foo {
#Get
#At("/bar")
public Reply<?> bar(Request<String> request, HttpSession session) {
// access request scoped HttpSession
}
}
If I understand sitebricks correctly, both Request and HttpSession are injected by sitebricks (potentially with the help of Guice). It will also ensure that the HttpSession is local to the current request. Concurrent requests will be executed on the same instance of Foo since the class is annotated with #Singleton (see Guice docs). But even with concurrent requests arriving on the same JVM, each invocation of bar() will have it's own HttpSession based on the JSESSIONID passed in by the client. Are all those assumptions valid?
When running load tests against my app, I have noticed that at a very low rate the HttpSession passed in by sitebricks/Guice is null. I am troubleshooting this with Google's support at the moment. But apart from GAE - What could cause this from the perspective of sitebricks/Guice?
I found a code snippet that injects a Provider into the constructor. Does that mean I can/should get the HttpSession by calling Provider.get() instead of letting sitebricks inject it as a method parameter?
Related Questions:
Provider<HttpSession> not getting injected
How to #Inject a HttpSession object in a service layer (DAO) class in GWT using Guice?
Inject #SessionScoped value into filter with Guice
Updates
I removed the HttpSession parameter from all the servlet methods like bar. I injected a Provider<HttpSession> into the servlet and call provider.get() to get the session. The tests that I ran so far indicate that this is more reliable than getting HttpSession out of the parameters. That said, I am not sure if the session is provided by sitebricks or GAE itself. Is the HttpSession provided by the servlet container?
Normally I inject HttpServletRequest into the service class first, and then get HttpSession object from the request, which has been working well for me.
For example:
#At("/preview")
#Service
public class PreviewService {
#Inject
private HttpServletRequest request;
// It's similar if we need to modify response directly
#Inject
private HttpServletResponse response;
#Get
public Reply<?> get() {
HttpSession session = request.getSession();
... ...
}
}
Hope it helps.
I am currently developing a Silverlight 3 app that needs some sort of user authentication, because the data pulled from a WCF service is user specific. Target audience is the regular Internet - so there is no AD to authenticate against.
Here are some of the questions I have concerning that situation:
Is there a framework or other mechanism that would support me?
Would you recommend authentication within the Silverlight app or via outside mechanisms like forms auth? Which is more secure?
What about out-of-browser support?
I used ASP.NET's authentication. Just use a MembershipProvider (or implement your own).
Then go to http://www.silverlightshow.net/items/Accessing-the-ASP.NET-Authentication-Profile-and-Role-Service-in-Silverlight.aspx to check out how you can expose the authentication service.
Then in your WCF service, you do the following (hosted in ASP):
public class MyWCFService : IMyWCFService
{
// retrieve your UserId from the MembershipProvider
private int GetUserId()
{
MembershipUser user = Membership.GetUser();
int userId = (int)user.ProviderUserKey;
return userId;
}
// check if user is authenticated
private bool IsUserAuthenticated()
{
return HttpContext.Current.User.Identity.IsAuthenticated;
}
public void Subscribe()
{
if (!IsUserAuthenticated())
{
throw new SecurityException("You must be authenticated to be able to use this service.");
}
int userId = GetUserId();
DoStuff(userId);
}
}
Hope that helps.
I would consider using the the authentication classes that exist in ASP.NET. You can then use .NET RIA Services (or even simply, WCF) to communicate with authentication service.
Consider this article as a primer.