美文网首页
chapter09_保护Web应用_5_选择查询用户详细信息的服

chapter09_保护Web应用_5_选择查询用户详细信息的服

作者: 米都都 | 来源:发表于2019-01-21 11:09 被阅读0次
    • 有的时候需要对用户的信息进行存储,以便判断登录进系统时的权限。我们需要的是用户存储,在进行认证决策的时候,进行检索

    • Spring Security内置了了多种数据存储方式来认证用户,包括内存关系型数据库LDAP

    • 使用基于内存的用户存储

      (1) 适用于开发、测试的场景,数据量小

      (2) 要重载 WebSecurityConfigurerAdapter的configure(AuthenticationManagerBuilder)方法,使用inMemoryAuthentication()方法进行基于内存的用户存储

      示例 SecurityConfig.java

        @Configuration
        @EnableWebMvcSecurity
        public class SecurityConfig extends WebSecurityConfigurerAdapter {
      
           ...
           
            @Override
            protected void configure(AuthenticationManagerBuilder auth) throws Exception {
      
                auth
                    .inMemoryAuthentication()
                    .withUser("user").password("password").roles("USER").
                    and.withUser("admin").password("password").roles("USER", "ADMIN");
            }
        }
      

      (3) withUser方法添加新的用户,返回类型为 UserDetailsManagerConfigurer,这个对象可以进一步做一系列的用户信息细节配置,详见P259

      (4) 使用and()方法可以继续添加新用户

    • 基于RDBMS的用户存储与认证

      (1) 示例 SecurityConfig.java

        import javax.sql.DataSource;
      
        @Configuration
        @EnableWebMvcSecurity
        public class SecurityConfig extends WebSecurityConfigurerAdapter {
      
            ...
      
            @Autowired
            DataSource dataSource;
      
            @Override
            protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
      
                auth.jdbcAuthentication().dataSource(dataSource).
                        usersByUsernameQuery("select username, password, true from Spitter " + "where username=?").
                        authoritiesByUsernameQuery("select username, 'ROLE_USER' from Spitter " + "where username=?").
                        passwordEncoder(new StandardPasswordEncoder());
            }
        }
      

      (2) 使用jdbcAuthentication()方法可以配置RDBMS型的用户存储,我们只需要自动装配@Autowired一个dataSource即可

      (3) 当直接使用

        auth.jdbcAuthentication().dataSource(dataSource);
      

      时,会采用默认的SQL语句,在SpringSecurity内置的JdbcDaoImpl类中

        public static final String DEF_USERS_BY_USERNAME_QUERY =
            "select username,password,enabled " +
            "from users " +
            "where username = ?";
        public static final String DEF_AUTHORITIES_BY_USERNAME_QUERY =
            "select username,authority " +
            "from authorities " +
            "where username = ?";
        public static final String DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY =
            "select g.id, g.group_name, ga.authority " +
            "from groups g, group_members gm, group_authorities ga " +
            "where gm.username = ? " +
            "and g.id = ga.group_id " +
            "and g.id = gm.group_id";
      

      但是,当数据库和默认的表名等不统一时,需要重写和以上三个SQL语句关联的方法;

      其中, usersByUsernameQuery()方法(认证查询)和DEF_USERS_BY_USERNAME_QUERY关联;authoritiesByUsernameQuery()方法(权限查询)和DEF_AUTHORITIES_BY_USERNAME_QUERY关联;groupAuthoritiesByUsername()方法(群组权限查询)和DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY关联

      (4) 以上的3个方法在自己配置时,要按照规定的协议来配置:

      所有的查询都将用户名username作为唯一的参数;

      认证查询会选取用户名、密码、启用状态;

      权限查询会选取用户名、权限信息;

      群组权限查询会选取群组id、群组名称、权限;

      即使数据库中包含上面要查询的某项,也要使用布尔值或字符串的方式进行填充(类似于"select username, password, true from Spitter where username=?"和"select username, 'ROLE_USER' from Spitter where username=?")

      (5) 使用转码后的密码

      用户的密码应该进行加密,然后存储在数据库中,使用passwordEncoder()方法就可以解决这个问题;

      数据库中的密码永远不会被解码,而是用户登录时输入的密码使用相同的算法进行加密,然后和数据库中转码后的密码进行对比

    相关文章

      网友评论

          本文标题:chapter09_保护Web应用_5_选择查询用户详细信息的服

          本文链接:https://www.haomeiwen.com/subject/ylaqjqtx.html