SpringSecurity-Two

SpringSecurity-Two

Scroll Down

在我前边写的springsecurity-zero中有一个简单的demo,这里对其进行详细解释

1. springsecurity默认的登录页面

  • 导入springsecurity依赖之后访问项目会发现有一个默认的登录页面 image.png
  • 当然可以关闭这个默认的登录页面,在application.yml文件中加入下边配置
security:
  basic:
    enabled: false
  • 如果不想关闭,那需要注意SpringBoot项目在启动的时候会在控制台打印一段密码,这个密码就是登录密码,用户名没有要求

2. 那怎么在项目中去配置自己的登录逻辑呢?这里要了解三个接口,第一个UserDetailsService接口

  • 这个接口只有一个抽象方法loadUserByUsername(),他需要返回一个UserDetails,这也是一个接口,后续会说到。loadUserByUsername需要接收一个参数,这个参数就是我们登录页面传递过来的用户名
public interface UserDetailsService {
	UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
  • 在开发中我们需要自己去写一个Service去实现这个接口,并复写loadUserByUsername方法,在该方法中就可以书写我们的登录逻辑
public class MyUserDetailsService implements UserDetailsService {
    private Logger logger = LoggerFactory.getLogger(getClass());
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        logger.info("登录用户名:"+username);
        return User();	//这里的这个User是springsecurity默认的User
    }
}

3. UserDetails接口,这个接口一般是我们自定义的User类去实现这个接口

public interface UserDetails extends Serializable {
	
	Collection<? extends GrantedAuthority> getAuthorities();

	
	String getPassword();

	
	String getUsername();

	
	boolean isAccountNonExpired();

	
	boolean isAccountNonLocked();

	
	boolean isCredentialsNonExpired();

	
	boolean isEnabled();
}
  • 这个接口中有七个方法,这里了解一下每个方法是用来做什么的
    • getAuthorities()方法返回的是一个集合类型,它是用来存放我们自定义User类中角色权限的。比如说A用户有"admin","user","superadmin"这三个权限,那么使用这个方法定义这三个权限
    • getPassword()方法返回的是一个String,他就是用来定义我们在数据中存储密码的。
    • getUsername()方法同getPassword(),用来定义用户名的
    • isAccountNonExpired()方法是判断账户是否过期
    • isAccountNonLocked()方法是判断账户是否锁定
    • isCredentialsNonExpired()方法是判断判断用户凭证是否已经过期
    • isEnabled()方法是判断用户是否可用
  • 这里我就不适用自定义User类来实现UserDetails接口了,直接使用默认的User
public class MyUserDetailsService implements UserDetailsService {
    private Logger logger = LoggerFactory.getLogger(getClass());
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
	logger.info("登录用户名:"+username);
	/**
         * 创建一个User,赋予这个user密码为123456,并且具有权限为"admin"
         */
	User user = new User(username,"123456",AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
        
        return user;	//这里的这个User是springsecurity默认的User
    }
}
  • 这样我们访问项目,就可以用123456这个密码来登陆了 image.png image.png

4. 我们会发现其实这样很不安全,密码在明文传输。springsecurity也考虑到了这一点,它提供了一个接口负责对密码进行加密,PasswordEncoder接口

public interface PasswordEncoder {

	String encode(CharSequence rawPassword);
	
	boolean matches(CharSequence rawPassword, String encodedPassword);

}
  • 这个接口有两个方法,下边详细说明一下这两个方法是用来做什么的
    • encode()当用户注册的时候可以调用这个方法将明文密码加密,再将加密之后的密码存放到数据库中
    • matches()当用户登录的时候,通过用户名查询到了当前用户名在数据库中对应的密码,然后就会调用这个方法判断登录请求过来的密码和数据库存放的密码是否匹配。
  • 首先需要将这个接口配置成spring中的Bean
@Configuration
public class BrowserSecurityConfig {
    @Bean
    public PasswordEncoder passwordEncoder(){
        /**
         * 这里返回的是spring默认的PasswordEncoder的实现类,用的也是默认的加密方法
         * 通过查看PasswordEncoder接口的源码可以看到有两个方法,一个是对传进来的数据进行加密的方法
         * 一个是调用这个方法,spring会自己判断传进来的数据是否符合加密规则
         * 如果需要使用自己的加密方法,那么这个方法要实现PasswordEncoder这个接口,然后返回
         */
        return new BCryptPasswordEncoder();
    }
}
  • 在我们自定义并实现UserDetailsService接口的类中,就可以使用PasswordEncoder了
@Component
public class MyUserDetailsService implements UserDetailsService {
    private Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        logger.info("登录用户名:"+username);
        /**
         * 根据用户名查找用户信息
         * 根据查找的用户信息判断用户是否被冻结
         * 这里返回的是spring默认的User对象,通过查看源码可以发现这个User对象实现了UserDetails接口
         * 在实际的开发中我们只需要让自己的User对象去实现UserDetails
         * 然后通过去数据库中查询到这个User对象,判断账户的一些信息
         * 例如是否被冻结,密码是否正确,具有什么权限,账户是否可用,总共七个。
         */
        String password = passwordEncoder.encode("123456");
        logger.info("数据库密码是:"+password);

        return new User(username,password,true,true,true,true, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}

  • 这样就可以将密文存储到数据中了。

以上就是springsecurity的简单了解,如需更多了解请关注后续文章。