Everytime i call subject.isPermitted(), it sends a sql to db.
How can i cache it? Any example? Thanks.
I read the doc of shiro grails plugin, but cant solove it.
DataSource:
hibernate {
cache.use_second_level_cache = true
cache.use_query_cache = true
cache.provider_class = 'net.sf.ehcache.hibernate.EhCacheProvider'
}
How to set the cachemanager to shiro? I try spring.resource,throw an error.
What's the instance bean name of cachemanager? Do i need to config sth else?
You'll need to configure an org.apache.shiro.cache.CacheManager instance on Shiro's SecurityManager. Most of Shiro's out-of-the-box Realm implementations know how to work with a configured CacheManager and will cache AuthorizationInfo returned from a Realm permission lookup automatically.
I'm not sure how to do this using the Grails Shiro plugin, but in Shiro's INI, you would do that this way:
[main]
...
cacheManager = com.my.implementation.of.CacheManager
securityManager.cacheManager = $cacheManager
...
I'd recommend asking the grails-user mailing list to see if there is a more 'grailsy' way to configure this for the Grails Shiro plugin.
HTH,
Les
Related
I'm using Spring Security Rest and the Grails Audit Logging plugin. Audit log records are being created with all the correct information except the actor property is always saved with the defaultActor value.
Below is my configuration. Does anyone have any ideas? What should I be looking for? Thanks in advance for your time.
build.gradle
ext.springSecurityRestVersion = '3.0.0.RC1'
dependencies {
...
compile "org.grails.plugins:spring-security-rest:${springSecurityRestVersion}"
compile "org.grails.plugins:spring-security-rest-gorm:${springSecurityRestVersion}"
compile 'org.grails.plugins:audit-logging:4.0.3'
...
}
application.yml
grails.plugin.auditLog:
auditDomainClassName: "us.mycompany.api.AuditLogEvent"
logFullClassName: false
defaultActor: "mycompany"
grails.plugin.springsecurity:
userLookup.userDomainClassName: 'us.mycompany.api.Person'
userLookup.authorityJoinClassName: 'us.mycompany.api.PersonRole'
authority.className: 'us.mycompany.api.Role'
filterChain.chainMap:
#Stateless chain
- { pattern: '/**', filters: 'JOINED_FILTERS,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter,-rememberMeAuthenticationFilter' }
rest.token:
storage.gorm.tokenDomainClassName: 'us.mycompany.api.AuthenticationToken'
validation:
useBearerToken: false
enableAnonymousAccess: true
As I debugged this, it seems like the springSecurityService dependency in SpringSecurityRequestResolver was null, so I had to explicitly wire SpringSecurityRequestResolver in resources.groovy.
I know that I shouldn't have to do that, but it did fix my problem, so this is at least a workaround.
resources.groovy
import grails.plugins.orm.auditable.resolvers.SpringSecurityRequestResolver
beans = {
auditRequestResolver(SpringSecurityRequestResolver) {
springSecurityService = ref('springSecurityService')
}
}
I am using two datasources in my Grails application. One is my local db and the other is remote db as shown below.
development {
dataSource {
url = "jdbc:mysql://localhost:3306/testax_dev?autoreconnect=true"
properties {
...
}
}
dataSource_phpscheduler {
driverClassName = 'com.mysql.jdbc.Driver'
username = "xyz"
password = "zxyz"
url = "jdbc:mysql://remote-ip:3306/phpscheduler?autoreconnect=true"
}
}
Now I want to handle the exception caused due to the connection problem of remote database so that the application starts successfully.
A Grails application will not start if the dataSource bean(s) can't be created. There is no way to start the application if the connection to the database fails.
The reason for this is that Grails depends on those beans being instanced, and ready.
Update
As pointed out by Burt Beckwith it is possible to do this, but it does require you to understand the lifecycle of Hibernate and your datasource. It's also possible to register your own dataSource which has error handling. As always, we owe much to Burt.
I have the Grails Spring Security plugin connecting to one Active Directory server with no problems. However, I need to connect to multiple servers. We have some users on one AD server and other users on a different server, so we need to try looking for users in both locations.
For example, in Java I have this working as below:
<authentication-manager>
<authentication-provider ref="provider1"/>
<authentication-provider ref="provider2"/>
...
</authentication-manager>
<ldap-server id="provider1"
url="ldap://LDAPSERVER1.mycompany.intranet"
manager-dn="OU=std_users,OU=users,DC=mycompany,DC=intranet"
manager-password="blah"/>
<ldap-server id="provider2"
url="ldap://DIFFERENT_LDAPSERVER.mycompany.intranet"
manager-dn="OU=std_users,OU=external_users,DC=mycompany,DC=intranet"
manager-password="blah"/>
In Grails I can configure one AD server but cannot work out how to configure more than one:
// LDAP config
grails.plugin.springsecurity.ldap.context.managerDn = 'CN=blah,OU=std_users,OU=users,DC=mycompany,DC=intranet'
grails.plugin.springsecurity.ldap.context.managerPassword = 'the_password'
grails.plugin.springsecurity.ldap.context.server = 'ldap://theserver.mycompany.intranet'
grails.plugin.springsecurity.ldap.authorities.ignorePartialResultException = true // typically needed for Active Directory
grails.plugin.springsecurity.ldap.search.base = 'OU=std_users,OU=users,DC=mycompany,DC=intranet'
grails.plugin.springsecurity.ldap.search.filter="sAMAccountName={0}" // for Active Directory you need this
grails.plugin.springsecurity.ldap.search.searchSubtree = true
grails.plugin.springsecurity.ldap.auth.hideUserNotFoundExceptions = false
I know that you can create a space-separated list of servers but this won't work for me as it will only try one of the servers once it has a connection, whereas I need it to try looking for users in both.
I think I probably need to get stuck into the resources.groovy file but don't know where to start with this - has anyone configured multiple AD locations?
The only other idea I have is to create a virtual directory which brings together all the users in one directory. Can anyone suggest a good way of doing this? I have been looking at http://myvd.sourceforge.net/usecases.html
Any help would be appreciated. Have been googling all day and I am no closer to a solution.
Andrew's answer pointed me in the right direction and I now have this working.
It was A LOT easier to make this work using ActiveDirectoryLdapAuthenticationProvider. This is done as below:
In resources.groovy:
// Domain 1
ldapAuthProvider1(ActiveDirectoryLdapAuthenticationProvider,
"mydomain.com",
"ldap://mydomain.com/"
)
// Domain 2
ldapAuthProvider2(ActiveDirectoryLdapAuthenticationProvider,
"mydomain2.com",
"ldap://mydomain2.com/"
)
In Config.groovy:
grails.plugin.springsecurity.providerNames = ['ldapAuthProvider1', 'ldapAuthProvider2']
This is all the code you need. You can pretty much remove all other grails.plugin.springsecurity.ldap.* settings in Config.groovy as they don't apply to this AD setup.
For documentation, see:
http://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ldap-active-directory
If you aren't using AD and want the 'pure LDAP' version:
In resources.groovy:
// Create another ldap authentication provider
ldapAuthProvider2(org.springframework.security.ldap.authentication.LdapAuthenticationProvider,
ref("ldapAuthenticator2"),
ref("ldapAuthoritiesPopulator") // Use default
) {
// Can set other auth provider settings here
}
ldapAuthenticator2(org.springframework.security.ldap.authentication.BindAuthenticator, ref("contextSource2")) {
userSearch = ref("ldapUserSearch2")
}
// Set up the manager to read LDAP
contextSource2(DefaultSpringSecurityContextSource, grailsApplication.config.grails.plugin.springsecurity.ldap.context.server2) {
userDn = grailsApplication.config.grails.plugin.springsecurity.ldap.context.managerDn2 // Manager DN
password = grailsApplication.config.grails.plugin.springsecurity.ldap.context.managerPassword2
}
// Configuration for searching for user
ldapUserSearch2(FilterBasedLdapUserSearch, grailsApplication.config.grails.plugin.springsecurity.ldap.search.base2, grailsApplication.config.grails.plugin.springsecurity.ldap.search.filter2, ref('contextSource2')) {
}
And then in Config.groovy:
// Config for second LDAP AuthenticationProvider - used in resources.groovy
grails.plugin.springsecurity.ldap.context.managerDn2 = 'CN=MANAGER_USER,OU=Users,DC=mycompany,DC=com'
grails.plugin.springsecurity.ldap.context.managerPassword2 = 'manager_password'
grails.plugin.springsecurity.ldap.context.server2 = "ldap://the-ldap-server.com"
grails.plugin.springsecurity.ldap.search.base2 = 'OU=Users,DC=mycompany,DC=com'
grails.plugin.springsecurity.ldap.search.filter2 = "sAMAccountName={0}" // for Active Directory you need this
// Add the AuthenticationProvider to the list
grails.plugin.springsecurity.providerNames = ['ldapAuthProvider', 'ldapAuthProvider2']
This link was very useful for finding out how to set this up:
https://github.com/grails-plugins/grails-spring-security-ldap/blob/master/SpringSecurityLdapGrailsPlugin.groovy
The basic idea would be to construct a second, custom AuthenticationProvider bean within your application's grails-app/conf/spring/resources.groovy file, perhaps modeling it after ldapAuthProvider in https://github.com/grails-plugins/grails-spring-security-ldap/blob/master/SpringSecurityLdapGrailsPlugin.groovy Then, you could add this custom LDAP authenticator bean to the grails.plugin.springsecurity.providerNames list in Config.groovy (or equivalent)
It seems that Grails is trying to access my database when I first deploy it to my production tomcat server. I know this because I get the following error message in the stacktrace.log
invalid username/password; login denied
Now, I disabled database creation
dataSource {
pooled = false
driverClassName = "oracle.jdbc.OracleDriver"
dialect = org.hibernate.dialect.Oracle10gDialect
}
hibernate {
cache.use_second_level_cache = true
cache.use_query_cache = false
cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory'
//Set jdbc metadata to false to not open a session
temp.use_jdbc_metadata_defaults = false
}
production {
dataSource {
dbCreate = "none"
url = "jdbc:oracle:thin:#1.1.1.1:1521:xe"
}
}
I don't supply the database password because we use database users for authentication and authorization (please don't criticize this decision, I know it's awful, but we have a legacy database). So the username/password is supplied when the user makes a request through the client. We used http://sergiosmind.wordpress.com/2013/03/14/grails-using-a-database-user-for-security-login/ to set this up.
It seems that the Grails app cannot start because of this. Why is Grails accessing the database? What is it trying to do?
Grails uses connections at startup to initialize GORM - there's one to detect the dialect, one to configure the LOB handler, and Hibernate connects to initialize its configuration also.
I discuss this in these two blog posts: http://burtbeckwith.com/blog/?p=312 and http://burtbeckwith.com/blog/?p=1565
How do you use a JDBCRealm to handle authenticating and authorizing users in servlets? The only example I can find is to create the DataSource in web.xml (such as Authentication against database using shiro 1.2.1).
I do not want to include database credentials in my source tree (for obvious reasons) and would prefer to use a Context defined DataSource via JNDI as I have for every other RDBMS I have used for any other purpose in every other servlet project I have developed.
How do you configure a Shiro JDBCRealm to obtain its DataSource from JNDI?
Vrushank's answer was really close: you don't need to subclass the JdbcRealm here - you can use Shiro's JndiObjectFactory to acquire the DataSource and then reference that DataSource when you configure the JdbcRealm:
[main]
dataSource = org.apache.shiro.jndi.JndiObjectFactory
dataSource.resourceName = java://app/jdbc/myDataSource
jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.dataSource = $dataSource
#addt'l config
For a web application, save the file under WEB-INF/shiro.ini.
See Also
https://github.com/danielmt/shiro-primefaces-example/blob/master/src/main/webapp/WEB-INF/shiro.ini
For Shiro to work with permissions with the JDBC realm this parameter is indispensable:
jdbcRealm.permissionsLookupEnabled = true
I wasted many hours on this because the default for this option is false. In other words, if you don't put this option Shiro always return an empty list of permissions.
I commented on #Les Hazlewood answer and on #Recurse comment, but might be that new answer is better option.
In my case I have to use only JDNI datasource name on weblogic and full path on tomcat:
Tomcat:
ds = org.apache.shiro.jndi.JndiObjectFactory
ds.requiredType = javax.sql.DataSource
ds.resourceName = java:/comp/env/oracle/pportal_dev
# JDBC realm config
jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.permissionsLookupEnabled = true
jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.dataSource = $ds
Weblogic
ds = org.apache.shiro.jndi.JndiObjectFactory
ds.requiredType = javax.sql.DataSource
ds.resourceName = oracle/pportal_dev
# JDBC realm config
jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.permissionsLookupEnabled = true
jdbcRealm.dataSource = $ds
Note
ds.resourceName = java:/comp/env/oracle/pportal_dev
vs
ds.resourceName = oracle/pportal_dev
You'll need to create a custom Realm of your own by extending JdbcRealm to programatically lookup the datasource through the provided JNDI.
You can then pass the JNDI as a property in shiro.ini
[main]
# realms to be used
customSecurityRealm=package.to.your.CustomRealm
customSecurityRealm.jndiDataSourceName=java:app/jdbc/myDatasource
See the below article as an example. It takes care of both Authentication and Authorization.
Apache Shiro JDBC Realm