Spring Security 配置用户列表

2016-12-08 17:16:57   最后更新: 2016-12-08 17:16:57   访问数量:401




上一篇日志中,我们介绍了 Spring Security 的基本内容,并且进行了初步的配置工作

Spring Secrity 简介及基本配置

本篇日志中,我们就来实现用户列表的配置

 

配置用户列表最简单的方法就是通过重载 WebSecurityConfigurerAdapter 的 configure 方法来实现用户列表的加载:

package com.techlog.test.testsecurity.configuration; import org.springframework.context.annotation.Configuration; 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.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; /** * SecurityConfig * Created by techlog on 2016/12/6. */ @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("bill").password("abc123").roles("USER"); auth.inMemoryAuthentication().withUser("admin").password("root123").roles("ADMIN"); auth.inMemoryAuthentication().withUser("dba").password("root123").roles("ADMIN", "DBA"); //dba have two roles. } }

 

 

在上面的这个配置中,我们重载了 configure 方法,并通过传入的 AuthenticationManagerBuilder 的 inMemoryAuthentication 方法启用了内存用户存储

我们配置了三个用户,定义了三种角色,其中 dba 用户同时拥有两种角色

我们也可以通过 and() 方法将多个配置连接起来:

package com.techlog.test.testsecurity.configuration; import org.springframework.context.annotation.Configuration; 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.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; /** * SecurityConfig * Created by techlog on 2016/12/6. */ @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("bill").password("abc123").roles("USER").and() .withUser("admin").password("root123").roles("ADMIN").and() .withUser("dba").password("root123").roles("ADMIN","DBA");//dba have two roles. } }

 

 

roles 方法是 authorities 方法的简写,.roles("ADMIN") 等效于 .authorities("ROLE_ADMIN")

 

AuthenticationManagerBuilder 提供的方法

AuthenticationManagerBuilder 提供的方法
方法描述
accountExpired(boolean)定义账号是否已经过期
accountLocked(boolean)定义账号是否已经锁定
and()用来连接配置
authorities(GrantedAuthority...)授予某个用户一项或多项权限
authorities(List)授予某个用户一项或多项权限
authorities(String...)授予某个用户一项或多项权限
credentialsExpired(boolean)定义凭证是否已经过期
disabled(boolean)定义账号是否已被禁用
password(String)定义用户的密码
roles(String...)授予某个用户一项或多项角色

 

通常基于内存的用户信息配置仅仅用于测试,生产环境中的用户数据通常保存在数据库中

 

Spring Security 实现了以 JDBC 为支撑的用户存储,我们可以使用 jdbcAuthentication 方法实现配置的获取:

@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.jdbcAuthentication().dataSource(dataSource).usersByUsernameQuery( "select username, password, true from techlog_user where username=?") .authoritiesByUsernameQuery( "select username, 'ROLE_USER' from techlog_user where username = ?"); }

 

 

在生产环境中,数据库通常不会存储用户的明文密码,而是需要对密码进行转码,AuthenticationManagerBuilder 提供了 passwordEncoder 方法实现对密码的转码

passwordEncoder 方法以一个 PasswordEncoder 接口对象作为参数,Spring 提供了三种 PasswordEncoder 的实现:

  1. BCryptPasswordEncoder
  2. NoOpPasswordEncoder
  3. StandardPasswordEncoder

 

PasswordEncoder 接口仅定义了两个方法,分别用来实现转码与判定是否相同,因此你也可以轻易的实现自己的 PasswordEncoder 类:

public interface PasswordEncoder { String encode(CharSequence var1); boolean matches(CharSequence var1, String var2); }

 

 

@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.jdbcAuthentication().dataSource(dataSource).usersByUsernameQuery( "select username, password, true from techlog_user where username=?") .authoritiesByUsernameQuery( "select username, 'ROLE_USER' from techlog_user where username = ?") .passwordEncoder(new StandardPasswordEncoder("password")); }

 

 

这样配置以后,用户在登录时输入的密码都会按照相同算法进行转码,然后再与数据库中存储的转码后的密码进行对比

 

更加复杂的情况,我们可能需要自己定义用户列表规则,比如用户列表存储在 MongoDB 或者 Neo4j 中,那么我们可以自己定义一个 UserDetailsService 接口来实现

public interface UserDetailsService { UserDetails loadUserByUsername(String username) throws UsernameNotFoundException; }

 

 

可以看到,这个接口是非常简单的,只有一个方法,通过传入的 username 参数获取用户描述类 UserDetails 对象,如果没有这个用户,那么只需在方法中抛出 UsernameNotFoundException 异常:

package com.techlog.test.testsecurity.service; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; import java.util.Arrays; /** * 用户验证服务 * Created by techlog on 2016/12/8. */ public class UserDetailsService implements org.springframework.security.core.userdetails.UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { if (!username.equals("techlog")) { throw new UsernameNotFoundException("user not found " + username); } return new User("username", "passworld", Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"), new SimpleGrantedAuthority("ROLE_ADMIN"))); } }

 

 

在 SecurityConfig 中,AuthenticationManagerBuilder 对象提供了userDetailsService 方法,用来加载我们的自定义用户配置:

@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(new UserDetailsService()); }

 

 






技术帖      config      龙潭书斋      java      spring      springmvc      configure      security      user     


京ICP备15018585号