zoukankan      html  css  js  c++  java
  • spring security基本知识(二) 自定义认证

    配置自定义的用户存储

    我们在 SecurityConfig 的配置类中 重写了 configure(AuthenticationManagerBuilder auth) 方法,我们可以通过 AuthenticationManagerBuilder 这个构造器类使用不同的用户存储,如 inMemoryAuthentication()基于内存的,jdbcAuthentication()基于关系型数据库的.

    通过查看AuthenticationManagerBuilder的源码可以发现里面还有一个方法 userDetailsService(),允许我们自定义用户存储的实现.如下:

    userDetailsService()方法 需要传入参数 “UserDetailsService”。而UserDetailsService是一个接口所以我们需要实现接口的loadUserByUsername(String s)方法。根据给定的用户名来查找用户。
    loadUserByUsername()方法会返回代表给定用户的UserDetails对象 。而这个UserDetail 又是个什么呢?我们再次产看其源码,发现这也是一个接口,也就是说我们还要实现这个 UserDetail接口.这个结构
    封装了用户的登陆信息

    好了,了解了 userDetailsService 方法的构造,我们就可以着手写代码了。首先定义一个 MyUserService 实现 UserDetailsService 接口.并在重写的 loadUserByUsername 方法中返回 UserDetail类型的对象即可。

    /**
     * @author cuiqq
     * @description: TODO
     * @date 2019-06-2115:36
     */
    public class MyUserService implements UserDetailsService {
        
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    
            //自定义用户存储数据来源,可以是从关系型数据库,非关系性数据库,或者其他地方获取用户数据。
            User userEntity = new User("cuiqq", "123456");
            //还可以在此设置账号的锁定,过期,凭据失效 等参数
            //...
    
            // 设置 权限,可以是从数据库中查找出来的
            ArrayList<GrantedAuthority> authorities = new ArrayList<>();
            authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
            authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
    
            userEntity.setAuthorities(authorities);
            return userEntity;
        }
    }
    @Data
    public class UserEntity implements UserDetails {
        /**
         * 用户名
         */
        private String username;
    
        /**
         * 密码
         */
        private String password;
    
        /**
         * 是否可用
         */
        private Boolean enabled;
    
        /**
         * 用户所拥有的权限
         */
        private List<? extends GrantedAuthority> authorities;
    
        /**
         * 用户的账号是否过期,过期的账号无法通过授权验证. true 账号未过期
         */
        private Boolean accountNonExpired = true;
    
        /**
         * 用户的账户是否被锁定,被锁定的账户无法通过授权验证. true 账号未锁定
         */
        private Boolean accountNonLocked = true;
    
        /**
         * 用户的凭据(pasword) 是否过期,过期的凭据不能通过验证. true 没有过期,false 已过期
         */
        private Boolean credentialsNonExpired = true;
    
        public UserEntity(String username, String password, Boolean enabled) {
            this.username = username;
            this.password = password;
            this.enabled = enabled;
        }
    
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return authorities;
        }
    
        @Override
        public String getPassword() {
            return password;
        }
    
        @Override
        public String getUsername() {
            return username;
        }
    
        @Override
        public boolean isAccountNonExpired() {
            return accountNonExpired;
        }
    
        @Override
        public boolean isAccountNonLocked() {
            return accountNonLocked;
        }
    
        @Override
        public boolean isCredentialsNonExpired() {
            return credentialsNonExpired;
        }
    
        @Override
        public boolean isEnabled() {
            return enabled;
        }
    }

    除了我们自定义的UserEntity外,还有一个 User,其实这就是Spring Security为我们实现好的 UserDetails 类.我们可以看到它的源码如下:

    public class User implements UserDetails, CredentialsContainer {
    
        private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
    
        // ~ Instance fields
        // ================================================================================================
        private String password;
        private final String username;
        private final Set<GrantedAuthority> authorities;
        private final boolean accountNonExpired;
        private final boolean accountNonLocked;
        private final boolean credentialsNonExpired;
        private final boolean enabled;
    
        //...
    }

    由于源码太长,这里只贴出一部分,可以看到这里面也有我们在UserEntity定义的字段.其实也不奇怪了,本来我们的 UserEntity 就是按着User进行改造的嘛.

    之所以自定义UserEntity,这里是为了方面初学者进行快速入门,相比于User我们的UserEntity还是很简单的.

    现在 我们的 UserDetailsService 已经完成了,接下来就是在 SecurityConfig 的configure方法中使用了,如下:

    /**
     * 自定义用户存储
     **/
    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        public void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(new MyUserService());
        }
    }
  • 相关阅读:
    记一次省赛总结
    护网杯一道密码学的感想
    配置phpstudy+phpstorm+xdebug环境
    python 模板注入
    hash扩展攻击本地实验
    kali rolling更新源之gpg和dirmngr问题
    web信息泄露注意事项
    ctf常见php弱类型分析
    文件上传小结
    ctf变量覆盖漏洞
  • 原文地址:https://www.cnblogs.com/cuiqq/p/11064827.html
Copyright © 2011-2022 走看看