栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Security学习02

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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 getAuthorities():获取所有权限

String getPassword():获取密码

String getUsername():获取用户名

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

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

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

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

public interface UserDetails extends Serializable {
    Collection 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 authorities) {
        this(username, password, true, true, true, true, authorities);
    }

    public User(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection 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的方法:

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去执行查询语句进行查询,再比较。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/353670.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号