Spring Boot整合Spring Security简记-高

作者: 78240024406c | 来源:发表于2018-01-16 11:59 被阅读447次

    new無语 转载请注明原创出处,谢谢!

    Spring Security学习目录

    上章硬编码了一个user用户。记录一点基础的配置,这次结合高级认证灵活使用Spring Security的用户认证。

    • AuthenticationManager: 身份验证的主要策略设置接口
    • ProviderManager: AuthenticationManager最常用的接口实现
    • AuthenticationProvider: ProviderManager的工作被委托者
    • Authentication: 认证用户信息主体
    • GrantedAuthority: 用户主体的权限
    • UserDetails: 用户的基本必要信息
    • UserDetailsService: 通过String username返回一个UserDetails

    • SecurityContextHolder: 提供访问 SecurityContext
    • SecurityContext: 保存Authentication,和一些其它的信息

    1. AuthenticationProvider

    ProviderManager把工作委托给AuthenticationProvider集合。ProviderManager将所有AuthenticationProvider进行循环,直到运行返回一个完整的Authentication,不符合条件或者不能认证当前Authentication,返回AuthenticationException异常或者null

    @Component
    public class SpringAuthenticationProvider implements AuthenticationProvider {
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication, "非验证类型");
            //账号
            String username = authentication.getName();
            //密码
            String password = authentication.getCredentials().toString();
            List<SimpleGrantedAuthority> roles = new ArrayList<>();
            if("testuser1".equalsIgnoreCase(username)){
                roles.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
            }else if("testuser2".equalsIgnoreCase(username)){
                roles.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
                roles.add(new SimpleGrantedAuthority("ROLE_DBA"));
            }else{
                throw new UsernameNotFoundException("用户名/密码无效");
            }
            return new UsernamePasswordAuthenticationToken(username, password, roles);
        }
    
        @Override
        public boolean supports(Class<?> authentication) {
            return (UsernamePasswordAuthenticationToken.class
                    .isAssignableFrom(authentication));
        }
    }
    

    此情况在AuthenticationManagerBuilder没有配置的情况下生效。(要把配置文件配置的用户账号/密码/角色配置信息注释掉)
    Collection<? extends GrantedAuthority>Authentication的角色信息。在认证成功返回时添加到Authentication中。
    supports(Class<?> authentication)方法是判断是否支持当前Authentication类型的认证。(JaasAuthenticationTokenOAuth2AuthenticationUsernamePasswordAuthenticationToken、自己实现)等。
    上面定义了两个用户,分别是testuser1testuser2,分别赋权ADMINROLE_ADMIN+ROLE_DBA(符合上章的权限请求路径)(Spring Security拦截器角色验证前缀"ROLE_")。
    运行项目进行测试角色是否正确。http://localhost:8080/login进行登录,分别访问http://localhost:8080/db/123http://localhost:8080/admin/123 返回404(有权限访问)或者403(无权限访问)。

    2. UserDetailsService

    实现UserDetailsService方法,提供UserDetails
    我们把上面的用户登录的查询功能挪动到UserDetailsSerivce接口实现中。

    @Service
    public class SpringUserDetailsService implements UserDetailsService {
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            UserDetails userDetails = null;
            List<GrantedAuthority> roles = new ArrayList<>();
            if ("testuser1".equalsIgnoreCase(username)) {
                roles.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
            } else if ("testuser2".equalsIgnoreCase(username)) {
                roles.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
                roles.add(new SimpleGrantedAuthority("ROLE_DBA"));
            } else {
                return null;
            }
            userDetails = new User(username, "password", roles);
            return userDetails;
        }
    }
    

    之后再对认证代码进行改动。

    @Component
    public class SpringAuthenticationProvider implements AuthenticationProvider {
    
        @Autowired
        private UserDetailsService userDetailsService;
    
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication, "非验证类型");
            //账号
            String username = authentication.getName();
            //密码
            String password = authentication.getCredentials().toString();
            List<SimpleGrantedAuthority> roles = new ArrayList<>();
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            if (userDetails == null) {
                throw new UsernameNotFoundException("用户名/密码无效");
            }
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password, roles);
            token.setDetails(userDetails);
            return token;
        }
    
        @Override
        public boolean supports(Class<?> authentication) {
            return (UsernamePasswordAuthenticationToken.class
                    .isAssignableFrom(authentication));
        }
    }
    
    

    3. PasswordEncoder

    Spring Security提供了很多加密方式,MD5、SHA、BCrypt等,官方推荐使用BCrypt,好处就不在这说了。自己百度下吧。提供的支持类就是BCryptPasswordEncoder。使用方式简单,直接初始化。注入就可以用了。两个方法加密、解密。
    PasswordEncoder

    /**
         * Encode the raw password. Generally, a good encoding algorithm applies a SHA-1 or
         * greater hash combined with an 8-byte or greater randomly generated salt.
         */
        String encode(CharSequence rawPassword);
    
        /**
         * Verify the encoded password obtained from storage matches the submitted raw
         * password after it too is encoded. Returns true if the passwords match, false if
         * they do not. The stored password itself is never decoded.
         *
         * @param rawPassword the raw password to encode and match
         * @param encodedPassword the encoded password from storage to compare with
         * @return true if the raw password, after encoding, matches the encoded password from
         * storage
         */
        boolean matches(CharSequence rawPassword, String encodedPassword);
    

    相关文章

      网友评论

      本文标题:Spring Boot整合Spring Security简记-高

      本文链接:https://www.haomeiwen.com/subject/qtzdoxtx.html