美文网首页
spring security的核心组件

spring security的核心组件

作者: pilisiyang | 来源:发表于2019-11-18 11:57 被阅读0次

    关于验证的核心组件

    介绍几个 spring security 中的核心组件

    • SecurityContextHolder
    • Authentication
    • AuthenticationManager
    • AuthenticationProvider
    • UserDetailsService

    SecurityContextHolder

    SecurityContextHolder是存放安全上下文(security context)的位置,当前用户身份,权限都在里面,默认采用本地线程(ThreadLocal)储存。

    可以通过它获取当前认证信息 Authentication

    通过 Authentication 可以获取到用户信息 UserDetails

    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    Object principal = auth.getPrincipal();
    UserDetails userDetails = (UserDetails) principal;
    

    Authentication

    Authentication 是认证信息的接口,可以通过它获取到用户的权限,密码,用户名,身份等等。

    package org.springframework.security.core;
    
    import java.io.Serializable;
    import java.security.Principal;
    import java.util.Collection;
    
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.core.context.SecurityContextHolder;
    
    
    public interface Authentication extends Principal, Serializable {
        
        Collection<? extends GrantedAuthority> getAuthorities();
    
        Object getCredentials();
    
        Object getDetails();
    
        Object getPrincipal();
    
        boolean isAuthenticated();
    
        void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
    }
    
    

    解释如下:

    • getAuthorities(),权限信息列表,未经过身份验证则为空集合。
    • getCredentials(),密码信息,在认证过后通常会被移除。
    • getDetails(),细节信息,默认实现接口为 WebAuthenticationDetails,它记录了访问者的ip地址和sessionId,项目中我们做了修改,增加了登陆方式的判断。
    import javax.servlet.http.HttpServletRequest;
    
    import org.springframework.security.web.authentication.WebAuthenticationDetails;
    
    /**
     * @author plsy
     */
    public class CustomWebAuthenticationDetails extends WebAuthenticationDetails {
        
        private static final long serialVersionUID = -2135894122511996600L;
        
        /**
         * 登录方式,phone:手机验证码登录,其他:用户名密码登录
         */
        private String type;
        
        /**
         * 是否为门户前端登录 0 否 1 是
         */
        private String front;
        
        /**
         * 是否移动端登录,用来控制设备信息
         */
        private String device;
    
        public CustomWebAuthenticationDetails(HttpServletRequest request) {
            super(request);
            type = request.getParameter("type");
            front = request.getParameter("front");
            device = request.getParameter("device");
        }
    
        public String gettype() {
            return type;
        }
        
        public String getFront() {
            return front;
        }
    
        public String getDevice() {
            return device;
        }
        
    }
    
    • getPrincipal(),用户身份信息,默认返回的是UserDetails接口的实现类,可以获取用户名,密码,是否过期,是否锁定等信息。
    package org.springframework.security.core.userdetails;
    
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.GrantedAuthority;
    
    import java.io.Serializable;
    import java.util.Collection;
    
    public interface UserDetails extends Serializable {
        
        String getPassword();
    
        String getUsername();
    
        boolean isAccountNonExpired();
    
        boolean isAccountNonLocked();
    
        boolean isCredentialsNonExpired();
    
        boolean isEnabled();
    }
    
    

    AuthenticationManager

    顾名思义 AuthenticationManager 就是用来管理 Authentication 的,它将来验证 Authentication 是否正确。

    那么它是如何验证的呢,首先 AuthenticationManager 是一个接口,而 ProviderManager 是它的实现类,在 ProviderManager 中维护了一个 List<AuthenticationProvider> 的集合,这个集合中保存的就是真正的验证器,存放了多种验证方式,实际上是设计模式中的委托模式的应用。

    项目中目前用到了jwt,用户名密码,手机短信,移动设备识别码这四种验证方式,在 spring security 的配置类中重写 authenticationManager 配置将 AuthenticationProvider 注册进去。

        @Override
        protected AuthenticationManager authenticationManager() throws Exception {
            //这里会轮询符合条件的AuthenticationProvider,如果成功就终止,不成功就下一个
            ProviderManager authenticationManager = new ProviderManager(Arrays.asList(jwtAuthenticationProvider(), daoAuthenticationProvider(), phoneAuthenticationProvider(), mobileDeviceAuthenticationProvider()));
            return authenticationManager;
        }
    

    AuthenticationProvider

    AuthenticationProvider 最常用的一个实现便是 DaoAuthenticationProvider ,也是 spring security 默认提供的,DaoAuthenticationProvider 会通过 retrieveUser 取回 UserDetails 然后与 UsernamePasswordAuthenticationToken 做对比,交给additionalAuthenticationChecks方法完成的。

        /**
         * 用户名密码的数据库验证器
         *
         * @return
         */
        @Bean
        DaoAuthenticationProvider daoAuthenticationProvider() {
            DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
            daoAuthenticationProvider.setPasswordEncoder(new PasswordEncoder() {
                @Override
                public String encode(CharSequence rawPassword) {
                    return MD5Util.encode((String) rawPassword);
                }
    
                @Override
                public boolean matches(CharSequence rawPassword, String encodedPassword) {
                    return encodedPassword.equals(MD5Util.encode((String) rawPassword));
                }
            });
            daoAuthenticationProvider.setUserDetailsService(customUserService());
            return daoAuthenticationProvider;
        }
    

    UserDetailsService

    UserDetailsService 负责从数据库中加载用户信息,UserDetailsService 常见的实现类有JdbcDaoImpl,InMemoryUserDetailsManager,前者从数据库加载用户,后者从内存中加载用户。

    在项目中我们自己实现 UserDetailsService,重写了 loadUserByUsername 方法,根据登录名读取整个用户信息,还设置了用户对应的权限项。

    package org.springframework.security.core.userdetails;
    
    public interface UserDetailsService {
        
        UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
    }
    
    

    相关文章

      网友评论

          本文标题:spring security的核心组件

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