3

您如何使用新的普通 Grails 3.0 应用程序将用户存储在数据库中?

背景:

  1. Shiro 和 Spring Security 插件还不能用于 Grails 3.0(听起来 Spring Boot 是 Grails 安全性的未来)。
  2. 有各种各样的例子展示了如何使用inMemoryAuthentication(),但它们似乎完全没有意义,因为密码最终以纯文本形式存储(此外,在 Grails 中创建域模型只需要大约 30 秒的时间)。
  3. 几乎所有 Grails 应用程序都需要这个功能。
  4. 我碰巧在使用 MongoDB,但这可能无关紧要。
  5. 相关:Grails 3 和 Spring Security 插件

我目前inMemoryAuthentication()正在处理以下内容:

构建.gradle

compile "org.springframework.boot:spring-boot-starter-security"


grails-app/conf/spring/resources.groovy

import com.tincanworks.AppSecurityConfig
beans = {
   webSecurityConfiguration(AppSecurityConfig)
   }


AppSecurityConfig.groovy

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter

class AppSecurityConfig extends WebSecurityConfigurerAdapter {

   @Override
   protected void configure(HttpSecurity http) throws Exception {
      http
         .authorizeRequests()
            .antMatchers("/").permitAll()
            .antMatchers("/assets/**").permitAll()
            .antMatchers("/admin/**").hasAnyRole("admin")
            .anyRequest().authenticated()
         .and()
            .formLogin().permitAll()
         .and()
            .logout().permitAll()
      }

   @Autowired
   public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
      auth
         .inMemoryAuthentication()
            .withUser("user").password("123456").roles("user")
            .and()
            .withUser("admin").password("1qaz2wsx").roles("user", "admin")
      }

}

似乎答案可能与JdbcDaoImpl有关,但我不知道如何在 Grails 中连接它。

4

2 回答 2

2

基于 GORM

我写了两篇关于如何在 Grails 3 应用程序中使用 spring-starter-security 和 GORM 的博文(第 1 部分 - 内存身份验证第 2 部分 - 基于 Gorm 的身份验证)。我还使用 spring-starter-security创建了一个带有工作 Grails 3 应用程序的 github 存储库。

基于 JDBC - 未经测试

或者,如果您想使用标准的基于 JDBC 的身份验证,您可以使用以下 SQL 脚本创建数据库表

数据库

来自http://docs.spring.io/spring-security/site/docs/3.0.x/reference/appendix-schema.html

create table users(
      username varchar_ignorecase(50) not null primary key,
      password varchar_ignorecase(50) not null,
      enabled boolean not null);

  create table authorities (
      username varchar_ignorecase(50) not null,
      authority varchar_ignorecase(50) not null,
      constraint fk_authorities_users foreign key(username) references users(username));
      create unique index ix_auth_username on authorities (username,authority);

MySQL

这来自http://justinrodenbostel.com/2014/05/30/part-5-integrating-spring-security-with-spring-boot-web/

create table users (
    username varchar(50) not null primary key,
    password varchar(255) not null,
    enabled boolean not null) engine = InnoDb;

create table authorities (
    username varchar(50) not null,
    authority varchar(50) not null,
    foreign key (username) references users (username),
    unique index authorities_idx_1 (username, authority)) engine = InnoDb;

然后将configureGlobal方法更改为

@Autowired  //not sure if this is needed as you have the AppSecurityConfig bean referenced in resources.groovy
def datasource  //bean injected by Grails

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
  auth
     .jdbcAuthentication()
     .dataSource(datasource)
}
于 2015-05-19T21:26:49.340 回答
0

如果您想避免使用数据库从头开始构建整个用户管理层,您可以考虑Stormpath

除此之外,它们还提供了一个Spring Security 插件,该插件使用 Stormpath 作为身份验证和授权提供者。他们还有一个示例 Spring Security 应用程序,显示了该插件的使用方式。由于您使用的是 Java Annotations(而不是 xml 配置),请查看此分支

因此,总而言之,您需要定义的关键部分是:

  1. Stormpath 客户端 Bean 将通过Stormpath Java SDK提供与 Stormpath 的快速安全通信:

    //Let's create the Stormpath client using the apiKey.properties file from the User's home folder.
    @Bean
    ClientFactory stormpathClient(CacheManager cacheManager) {
        ClientFactory clientFactory = new ClientFactory();
        clientFactory.setApiKeyFileLocation(System.getProperty("user.home") + File.separator + ".stormpath" + File.separator + "apiKey.properties");
        clientFactory.setCacheManager(cacheManager);
        return clientFactory;
    }
    
  2. 您将需要定义 Stormpath Authentication Provider 以便 Spring Security 可以透明地与 Stormpath 通信以对用户进行身份验证和授权:

    @Bean
    @Autowired
    public StormpathAuthenticationProvider stormpathAuthenticationProvider(Client client, String applicationRestUrl) throws Exception {
        StormpathAuthenticationProvider stormpathAuthenticationProvider = new StormpathAuthenticationProvider();
        stormpathAuthenticationProvider.setClient(client);
        stormpathAuthenticationProvider.setApplicationRestUrl(applicationRestUrl);
        return stormpathAuthenticationProvider;
    }
    
  3. applicationRestUrl需要指向所有用户/组都将存在的 Stormpath 应用程序:

    @Bean
    public String getApplicationRestUrl() {
        return "https://api.stormpath.com/v1/applications/9TqbyZ2po73eDP4gYo2H92";
    }
    
  4. 您的 Spring Security 配置需要配置为使用 Stormpath Authentication Provider:

    //Let's add the StormpathAuthenticationProvider to the `AuthenticationProvider`
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(stormpathAuthenticationProvider);
    }
    
  5. 最后,为了限制角色对资源的访问,您需要定义角色。例如:

    //The access control settings are defined here
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .formLogin()
                .and()
            .authorizeRequests()
                .accessDecisionManager(accessDecisionManager())
                .antMatchers("/account/*").hasAuthority("https://api.stormpath.com/v1/groups/36O9eBTN2oLtjoMSWLdnwL") //you are giving access to "/account/*" to users' that belong to the group univocally identified by this href value
                .and()
            .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/index.jsp")
                .and()
            .httpBasic()
            .and()
            .csrf().disable();
    }
    

免责声明,我是一名活跃的 Stormpath 贡献者。

于 2015-05-08T19:50:09.793 回答