Getting the number of currently logged in users from spring security core plugin in grails - spring

I'm trying to get the number of currently logged in grails application. I'm using:
Grails 2.3.1 and spring-security-core:2.0-RC2 plugin.
By refering to this thread:
GRAILS: how to get the number of currently signed in users via spring security core plugin?
resources.groovy
import org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy
beans = {
sessionRegistry(org.springframework.security.core.session.SessionRegistryImpl)
concurrencyFilter(org.springframework.security.web.session.ConcurrentSessionFilter){
sessionRegistry = sessionRegistry
expiredUrl = '/login/concurrentSession'
}
sessionAuthenticationStrategy(ConcurrentSessionControlStrategy, sessionRegistry) {
maximumSessions = -1
}
}
I also modified web.xml and added:
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
These are the only changes that I made to my application.
Modifying BootStrap in such fashion
class BootStrap {
def springSecurityService
def authenticationManager
def concurrentSessionController
def securityContextPersistenceFilter
def init = { servletContext ->
authenticationManager.sessionController = concurrentSessionController
}
def destroy = {
}
}
Causes error on start-up:
Error initializing the application: No such property: sessionController for class: org.springframework.security.authentication.ProviderManager
Message: No such property: sessionController for class: org.springframework.security.authentication.ProviderManager
The only think that I accomplished so far is that SessionRegistry is injected to my controller and I'm able to invoke
sessionRegistry.getAllPrincipals().size()
without getting NullPointerException but it returns 0 no matter how many users are currently logged in.
I don't know where to proceed from here since I'm a beginner with spring.

Related

Spring Framework: setDefaultProfiles method does not work as expected as the "-Dspring.profiles.default" property

For Spring Framework 6 having some #Configuration classes with the #Profile("default") and #Profile("prod") respectively. Exists the following scenarios:
Scenario I
ctx = new AnnotationConfigApplicationContext("com.manuel.jordan.config");
When is executed the Main class with the -Dspring.profiles.default=default,prod property, through:
System.out.println("Default Profiles");
for(String defaultProfile : ctx.getEnvironment().getDefaultProfiles()) {
System.out.println(" " + defaultProfile);
}
I can see both profiles being listed and is possible retrieve the #Bean from these #Configuration classes based with the #Profile("default") and #Profile("prod") profiles. Until here all work as expected. Therefore is confirmed that these two default profiles were applied to the Spring Application Context for the beans creation process.
Scenario II
With
ctx = new AnnotationConfigApplicationContext("com.manuel.jordan.config");
ctx.getEnvironment().setDefaultProfiles("default", "prod");
or even with
ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setDefaultProfiles("default", "prod");
ctx.scan("com.manuel.jordan.config");
ctx.refresh();
When is executed the Main class without the -Dspring.profiles.default=default,prod property, because now is used .setDefaultProfiles("default", "prod") instead, through:
System.out.println("Default Profiles");
for(String defaultProfile : ctx.getEnvironment().getDefaultProfiles()) {
System.out.println(" " + defaultProfile);
}
I can see both profiles being listed but is not possible retrieve the #Bean from these #Configuration classes, again, based with the #Profile("default") and #Profile("prod") profiles - both profiles were ignored because each one throws the NoSuchBeanDefinitionException type. Why here is failing?
Question
Why did -Dspring.profiles.default=default,prod work and .setDefaultProfiles("default", "prod") did not work?

Problem with connection to Neo4j test container using Spring boot 2 and JUnit5

Problem with connection to Neo4j test container using Spring boot 2 and JUnit5
int test context. Container started successfully but spring.data.neo4j.uri property has a wrong default port:7687, I guess this URI must be the same when I call neo4jContainer.getBoltUrl().
Everything works fine in this case:
#Testcontainers
public class ExampleTest {
#Container
private static Neo4jContainer neo4jContainer = new Neo4jContainer()
.withAdminPassword(null); // Disable password
#Test
void testSomethingUsingBolt() {
// Retrieve the Bolt URL from the container
String boltUrl = neo4jContainer.getBoltUrl();
try (
Driver driver = GraphDatabase.driver(boltUrl, AuthTokens.none());
Session session = driver.session()
) {
long one = session.run("RETURN 1",
Collections.emptyMap()).next().get(0).asLong();
assertThat(one, is(1L));
} catch (Exception e) {
fail(e.getMessage());
}
}
}
But SessionFactory is not created for the application using autoconfiguration following to these recommendations - https://www.testcontainers.org/modules/databases/neo4j/
When I try to create own primary bean - SessionFactory in test context I get the message like this - "URI cannot be returned before the container is not loaded"
But Application runs and works perfect using autoconfiguration and neo4j started in a container, the same cannot be told about the test context
You cannot rely 100% on Spring Boot's auto configuration (for production) in this case because it will read the application.properties or use the default values for the connection.
To achieve what you want to, the key part is to create a custom (Neo4j-OGM) Configuration bean. The #DataNeo4jTest annotation is provided by the spring-boot-test-autoconfigure module.
#Testcontainers
#DataNeo4jTest
public class TestClass {
#TestConfiguration
static class Config {
#Bean
public org.neo4j.ogm.config.Configuration configuration() {
return new Configuration.Builder()
.uri(databaseServer.getBoltUrl())
.credentials("neo4j", databaseServer.getAdminPassword())
.build();
}
}
// your tests
}
For a broader explanation have a look at this blog post. Esp. the section Using with Neo4j-OGM and SDN.

Amazon Web Services - Deploy Spring Boot Application

I have a spring boot application that I am deploying onto EB (Elastic Beanstalk) AWS. The app works fine locally, however, I get a 404 on all pages I try to access on the deployed version. Also, I can't access any of the static content under the static folder either. All REST endpoints work fine.
My project structure is as follows
-- src
-- main
-- kotlin
-- resources
-- static
-- css
-- fonts
-- images
-- js
-- templates (contains html files)
I've tried defining option_settings in a .config file under a .ebextensions folder
option_settings
aws:elasticbeanstalk:container:java:staticfiles:
/public/: WEB-INF/classes/static
/static/: WEB-INF/classes/staticenter code here
I've also tried adding the following to my spring configuration class
#Configuration open class MvcConfig : WebMvcConfigurerAdapter() {
override fun addViewControllers(registry: ViewControllerRegistry) {
registry.addViewController("/").setViewName("homepage")
registry.addViewController("/index").setViewName("homepage")
registry.addViewController("/home").setViewName("homepage")
registry.addViewController("/homepage").setViewName("homepage")
registry.addViewController("/login").setViewName("login")
registry.addViewController("/products").setViewName("productsList")
registry.addViewController("/productdetail").setViewName("productDetail")
}
#Bean
open fun viewResolver(): ViewResolver {
val bean = InternalResourceViewResolver()
bean.setPrefix("/templates/")
bean.setSuffix(".html")
return bean
}
override fun addResourceHandlers(registry: ResourceHandlerRegistry?) {
// Register resource handler for all static folders
registry!!.addResourceHandler("/resources/**").addResourceLocations("classpath:/statics/")
.setCacheControl(CacheControl.maxAge(2, TimeUnit.HOURS).cachePublic())
}
#Bean
open fun errorPageFilter(): ErrorPageFilter {
return ErrorPageFilter()
}
#Bean
open fun disableSpringBootErrorFilter(filter: ErrorPageFilter): FilterRegistrationBean {
val filterRegistrationBean = FilterRegistrationBean()
filterRegistrationBean.filter = filter
filterRegistrationBean.isEnabled = false
return filterRegistrationBean
}
I am deploying onto tomcat8 that sits behind an Apache proxy server.
My EB settings are correct as I tried to deploy a simpler application onto the instance, which worked fine.
Please let me know if there are any further details I need to provide
The issue was related to the resourceHandler, the classpath it self was never added to the resource handler, even though servlet logging was indicating it was.
Spring by default maps the following paths
classpath:META-INF/resources/
classpath:resources/
classpath:static/
classpath:public/
needed to add the /** to the mapping. The solution was to modify the code to the following
override fun addResourceHandlers(registry: ResourceHandlerRegistry?) {
registry!!.addResourceHandler("/**", "/static/**")
.addResourceLocations("classpath:/templates/", "classpath:/static/").setCacheControl(CacheControl.maxAge(2,TimeUnit.HOURS).cachePublic())
}
#Bean
open fun viewResolver(): ViewResolver {
val bean = InternalResourceViewResolver()
bean.setSuffix(".html")
return bean
}

grails/spring security - issue on get all connected users

I followed an article to get all connected users with spring securty in Grails, but it failed at getAllPrincipals method:
"Message: Cannot invoke method getAllPrincipals() on null object"
The code:
resources.groovy
import org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy
import org.springframework.security.web.session.ConcurrentSessionFilter
import org.springframework.security.core.session.SessionRegistryImpl
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy
beans = {
sessionRegistry(SessionRegistryImpl)
sessionAuthenticationStrategy(ConcurrentSessionControlStrategy, sessionRegistry) {
maximumSessions = -1
}
concurrentSessionFilter(ConcurrentSessionFilter){
sessionRegistry = sessionRegistry
expiredUrl = '/login/concurrentSession'
}
}
web.xml
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
controller
def sessionRegistry
def users= new ArrayList<User>(sessionRegistry.getAllPrincipals())
http://classpattern.com/spring-security-sessionregistry-on-grails.html#.U5GICfl_uhF
install templates: grails install-templates
web.xml will be found in : src/templates/war
Be sure that listener tag is before servlet tag :
Get all users :
sessionRegistry.getAllPrincipals().collect{User.get(it.id)}
I found this problem and what my solution is to declare sessionRegistry as variable class for example
class DummyController {
def sessionRegistry
def index() {
def users= new ArrayList<User>(sessionRegistry.getAllPrincipals())
}
}

spring security logout handler not working

i have grails pluggin spring-security-core-1.2.1
I registered security event listener as a spring bean in grails-app/conf/spring/resources.groovy:
securityEventListener(LoggingSecurityEventListener)
and make two additions to grails-app/conf/Config.groovy:
grails.plugins.springsecurity.useSecurityEventListener = true
grails.plugins.springsecurity.logout.handlerNames =
['rememberMeServices',
'securityContextLogoutHandler',
'securityEventListener']
my logging/logout listener
class LoggingSecurityEventListener implements ApplicationListener<AbstractAuthenticationEvent>, LogoutHandler {
void onApplicationEvent(AbstractAuthenticationEvent event) {
System.out.println('appEvent')
}
void logout(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) {
System.out.println('logout')
}
}
on ApplicationEvent works good, but logout not working
what could be the problem?
or you can tell how to get all logging users
When you set
grails.plugins.springsecurity.useSecurityEventListener = true
the spring security plugin will register it's own event listener called securityEventListener. The handler looked up from handlerNames is probably getting the plugin registered one instead of yours. Try renaming your bean to something like:
loggingSecurityEventListener(LoggingSecurityEventListener)
and replacing the handlerNames with
grails.plugins.springsecurity.logout.handlerNames =
['rememberMeServices',
'securityContextLogoutHandler',
'loggingSecurityEventListener']
NOTE: the configuration property names have changed (plugins -> plugin). If you're using the grails spring-security plugin version 2.0 or later, use this:
grails.plugin.springsecurity.logout.handlerNames

Resources