SpringSecurity(01)

简单配置

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-securityartifactId>
    <version>2.3.12.RELEASEversion>
dependency>
@Controller
public class UserController {
    
    @GetMapping("/test")
    @ResponseBody
    public String test(){
        return "hello";
    }
}

注意:导入依赖之后,请求地址会自动跳转到/login中,出现一个表单,用户名为user,密码在控制台出现
SpringSecurity(01)_第1张图片
SpringSecurity(01)_第2张图片

将表单请求转换为弹出框请求

/**
 * 定制用户认证管理器来实现用户认证
 *  1. 提供用户认证所需信息(用户名、密码、当前用户的资源权)
 *  2. 可采用内存存储方式,也可能采用数据库方式
 */
void configure(AuthenticationManagerBuilder auth);

/**
 * 定制基于 HTTP 请求的用户访问控制
 *  1. 配置拦截的哪一些资源
 *  2. 配置资源所对应的角色权限
 *  3. 定义认证方式:HttpBasic、HttpForm
 *  4. 定制登录页面、登录请求地址、错误处理方式
 *  5. 自定义 Spring Security 过滤器等
 */
void configure(HttpSecurity http);

/**
 * 定制一些全局性的安全配置,例如:不拦截静态资源的访问
 */
void configure(WebSecurity web);
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        /**
         * fromLogin():表单认证
         * httpBasic():弹出框认证
         * authorizeRequests():身份认证请求
         * anyRequest():所有请求
         * authenticated():身份认证
         */
        http.httpBasic()
                .and()
                .authorizeRequests()
            	// 其它任何请求访问都需要先通过认证
                .anyRequest()
                .authenticated();
    }
}

SpringSecurity(01)_第3张图片

自定义用户信息

配置文件自定义用户名和密码

spring:
  security:
    user:
      name: root    #通过配置文件,设置静态用户名
      password: root    #配置文件,设置静态登录密码

基于内存存储认证信息

  1. 在 Spring Security 5.0 版本前,加密的 PasswordEncoder 接口默认实现类为 NoOpPasswordEncoder ,这个是可以不用加密的,直接使用明文密码存储。当前已经标注过时了。
  2. 在 Spring Security 5.0 版本后 ,默认实现类改为了 DelegatingPasswordEncoder ,这个实现类要求我们必须对加密后存储。
@Configuration
@Slf4j
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 密码编码器,密码不能明文存储
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        // 设置默认的加密方式,使用 BCryptPasswordEncoder 密码编码器,
        // 该编码器会将随机产生的 salt 混入最终生成的密文中
        return new BCryptPasswordEncoder();
    }
    
    /**
     * 定制基于 HTTP 请求的用户访问控制
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        /**
         * fromLogin():表单认证
         * httpBasic():弹出框认证
         * authorizeRequests():身份认证请求
         * anyRequest():所有请求
         * authenticated():身份认证
         */
        http.httpBasic()
                .and()
                .authorizeRequests()
            	// 其它任何请求访问都需要先通过认证
                .anyRequest()
                .authenticated();
    }

    /**
    * 认证管理器:
    * 1、认证信息提供方式(用户名、密码、当前用户的资源权限)
    * 2、可采用内存存储方式,也可能采用数据库方式等
    */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 用户信息存储在内存中
        String password = passwordEncoder().encode("1234");
        logger.info("加密之后存储的密码:" + password);
        auth.inMemoryAuthentication()
        	.withUser("admin")
        	.password(password)
        	.authorities("ADMIN");
    }
    
    /**
     * 定制一些全局性的安全配置,例如:不拦截静态资源的访问
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        // 静态资源的访问不需要拦截,直接放行
        web.ignoring().antMatchers("/**/*.css", "/**/*.js", "/**/*.png", "/**/*.jpg", "/**/*.jpeg");
    }
}

UserDetailsService自定义登录请求

在实际开发中,Spring Security应该动态的从数据库中获取信息进行自定义身份认证,采用数据库方式进行身份认证一般需要实现两个核心接口 UserDetailsService 和 UserDetails

UserDetailService接口

该接口只有一个方法 loadUserByUsername(),用于定义从数据库中获取指定用户信息的逻辑。如果未获取到用户信息,则需要手动抛出 UsernameNotFoundException 异常;如果获取到用户信息,则将该用户信息封装到 UserDetails 接口的实现类中并返回

public interface UserDetailsService {
    // 输入参数 username 是前端传入的用户名
    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}

UserDetails接口

UserDetails接口定义了用于描述用户信息的方法

public interface UserDetails extends Serializable {
    // 返回用户权限集合
    Collection<? extends GrantedAuthority> getAuthorities();

    // 返回用户的密码
    String getPassword();

    // 返回用户的用户名
    String getUsername();

    // 账户是否未过期(true 未过期, false 过期)
    boolean isAccountNonExpired();

    // 账户是否未锁定(true 未锁定, false 锁定)
    // 用户账户可能会被封锁,达到一定要求可恢复
    boolean isAccountNonLocked();

    // 密码是否未过期(true 未过期, false 过期)
    // 一些安全级别高的系统,可能要求 30 天更换一次密码
    boolean isCredentialsNonExpired();

    // 账户是否可用(true 可用, false 不可用)
    // 系统一般不会真正的删除用户信息,而是假删除,通过一个状态码标志用户是否被删除
    boolean isEnabled();
}

用户登录逻辑处理

@Slf4j
@Component
public class UserDetailServiceImpl implements UserDetailsService {

    /**
     * Spring Security接收login请求调用UserDetailService这个接口中的loadUserByUsername
     * loadUserByUsername根据传进来的用户名进行校验工作,
	 * 最后将查询到的用户信息封装到UserDetails这个接口的实现类中
     */
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        log.info("登录用户名:{}",s);
        //根据用户名查询用户数据
        return new User(s,"123456", AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}

在使用了Spring Security-5.x版本,需要手动提供一个PasswordEncoder实现类,进行密码校验,PasswordEncoder是SpringSecurity的密码解析器,用户密码校验、加密,自定义登录逻辑时要求必须给容器注入PasswordEncoder的bean对象

@Component
public class PasswordEncoderImpl implements PasswordEncoder {
    
    @Override
    public String encode(CharSequence charSequence) {
        return charSequence.toString();
    }

    @Override
    public boolean matches(CharSequence charSequence, String s) {
        return s.equals(charSequence.toString());
    }
}

@Configuration
@Slf4j
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

	@Resource
    private PasswordEncoder passwordEncoder;
	@Resource
    private UserDetailsService userDetailsService;
    
    /**
     * 定制基于 HTTP 请求的用户访问控制
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        /**
         * fromLogin():表单认证
         * httpBasic():弹出框认证
         * authorizeRequests():身份认证请求
         * anyRequest():所有请求
         * authenticated():身份认证
         */
        http.httpBasic()
                .and()
                .authorizeRequests()
            	// 其它任何请求访问都需要先通过认证
                .anyRequest()
                .authenticated();
    }

    /**
    * 认证管理器:
    * 1、认证信息提供方式(用户名、密码、当前用户的资源权限)
    * 2、可采用内存存储方式,也可能采用数据库方式等
    */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 不再使用内存方式存储用户认证信息,而是动态从数据库中获取
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
    }
    
    /**
     * 定制一些全局性的安全配置,例如:不拦截静态资源的访问
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        // 静态资源的访问不需要拦截,直接放行
        web.ignoring().antMatchers("/**/*.css", "/**/*.js", "/**/*.png", "/**/*.jpg", "/**/*.jpeg");
    }
}

你可能感兴趣的:(SpringSecurity,spring,java)