Spring Security学习02

原理

Spring Security 本质上是一个过滤器链,含有很多过滤器,从启动是可以获取到过滤链的。(JAVA WEB 过滤器)

使用Spring Boot 提供了自动化配置 Spring Security 的方案,可以使用更少的配置来使用 Spring Security。

其中有三个较为重要的过滤器:

  • FilterSecurityInterceptor:是一个方法级的权限过滤器,基本位于过滤链的最底部。

  • ExceptionTranslationFilter:是一个异常过滤器,用来处理在认证授权过程中抛出的异常。

  • UsernamePasswordAuthenticationFilter:对/login 的 POST 请求做拦截,检验表中的用户名、密码。

UserDetailsService接口----自定义逻辑

当我们对Spring Security没有任何配置的时候,用户账号密码都是由Spring Security定义默认生成的。用户名默认为 username,密码自动在每次运行时在控制台生成。

自定义逻辑控制认证逻辑,从数据库中查询用户的ID和密码写在该接口下。该接口的主要作用是:查询数据库用户ID和密码

UserDetailsService接口下有一个抽象方法,在不同的项目下,根据实际情况创建实现类重写这个方法,实现查询数据库查询用户名和ID的功能。



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

这个方法的返回类型也是接口,也需要有一个实现类,其各种抽象方法的作用如下:

Collection<? extends GrantedAuthority> getAuthorities():获取所有权限

String getPassword():获取密码

String getUsername():获取用户名

boolean isAccountNonExpired():验证用户是否过期

boolean isAccountNonLocked():验证用户账号是否被锁定

boolean isCredentialsNonExpired():验证凭证(密码)是否过期

boolean isEnabled():验证用户是否可用

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

    String getPassword();

    String getUsername();

    boolean isAccountNonExpired();

    boolean isAccountNonLocked();

    boolean isCredentialsNonExpired();

    boolean isEnabled();
}

在Spring Security中已经给我们提供了UserDetails的实体类User,其全名路径为org.springframework.security.core.userdetails.User 。在我们项目创建过程中,需要注意别将我们的User类和内置的User类混淆!

对于内置User类,里面提供了很多方法和属性,其中构造方法有两个,调用其中任何一个都可以实例化,而三个参数的构造方法实际上也是调用 7 个参数的构造方法。

  • username:用户名

  • password:密码

  • authorities:用户具有的权限。此处不允许为 null

public User(String username, String password, Collection<? extends GrantedAuthority> authorities) {
        this(username, password, true, true, true, true, authorities);
    }

    public User(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
        Assert.isTrue(username != null && !"".equals(username) && password != null, "Cannot pass null or empty values to constructor");
        this.username = username;
        this.password = password;
        this.enabled = enabled;
        this.accountNonExpired = accountNonExpired;
        this.credentialsNonExpired = credentialsNonExpired;
        this.accountNonLocked = accountNonLocked;
        this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
    }

在User类中的username应为客户端(client)传来的用户名,密码应为数据库查询到的密码。Spring Security会根据查询到的密码(password)和客户端传入的密码(password)进行比较。如果相同,则认证成功,否则认证失败。

authorities中的权限反映该用户的权限,即该用户所能做的事情,如果某个用户没有拥有某个权限而去访问某个需要权限的事情,就会出现403页面。

PasswordEncoder 密码解析器

Spring Security中要求IOC容器中必须要有PasswordEncoder的实例,故自定义登录逻辑时,需要给容器注入PasswordEncoder的Bean对象。

PasswordEncoder接口中含有三个方法:

  • encode():把参数按照特定的解析规则进行解析。

  • matches() :验证从存储中获取的编码密码与编码后提交的原始密码是否匹配。如果密码匹配,则返回 true;如果不匹配,则返回 false。第一个参数表示需要被解析的密码(即客户端传入的密码),第二个参数表示存储的密码(数据库中对应的密码)。

  • upgradeEncoding():如果解析的密码能够再次进行解析且达到更安全的结果则返回 true,否则返回 false。默认返回 false。

public interface PasswordEncoder {
    String encode(CharSequence var1);

    boolean matches(CharSequence var1, String var2);

    default boolean upgradeEncoding(String encodedPassword) {
        return false;
    }
}

在测试类中测试PasswordEncoder的方法:

/**
 * 测试方法 BCryptPasswordEncoder 用法
 */
public class BCryptPasswordEncoderTest {

    @Test
    public void test(){
        //创建解析器
        PasswordEncoder pw = new BCryptPasswordEncoder();
        //对密码加密
        String encode = pw.encode("123");
        System.out.println("根据Hash加密后的密码:");
        System.out.println(encode);

        //判断原字符和加密后内容是否匹配
        boolean matches = pw.matches("123", encode);
        // boolean matches = pw.matches("124", encode);
        System.out.println("=============================\n"
                            +"判断原字符和加密后的内容是否相同");
        System.out.println(matches);
    }
}

 

客户端的password和数据库中的password相同时,结果为:

客户端的password和数据库中的password不同时,结果为:

此处的测试没有引入数据库,直接赋值进行比较观察结果。引入数据库的操作需先在依赖中引入相关依赖,再配置数据库,通过mybatis或者mybatisplus或者JPA去执行查询语句进行查询,再比较。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

programming_rooike

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值