zoukankan      html  css  js  c++  java
  • spring security 自定义多种方式登录授权

    自定义token,继承 AbstractAuthenticationToken

    import org.springframework.security.authentication.AbstractAuthenticationToken;
    import org.springframework.security.core.GrantedAuthority;
    
    import java.util.Collection;
    
    /**
     * 手机短信token验证
     *
     * @author ming
     * @version 1.0.0
     * @date 2021/3/1 15:17
     **/
    public class SmsAuthenticationToken extends AbstractAuthenticationToken {
    
        private static final long serialVersionUID = 530L;
        private final Object principal;
        private Object credentials;
    
        public SmsAuthenticationToken(Object principal, Object credentials) {
            super((Collection) null);
            this.principal = principal;
            this.credentials = credentials;
            this.setAuthenticated(false);
        }
    
        public SmsAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
            super(authorities);
            this.principal = principal;
            this.credentials = credentials;
            super.setAuthenticated(true);
        }
    
        @Override
        public Object getCredentials() {
            return this.credentials;
        }
    
        @Override
        public Object getPrincipal() {
            return this.principal;
        }
    
        @Override
        public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
            if (isAuthenticated) {
                throw new IllegalArgumentException("Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
            } else {
                super.setAuthenticated(false);
            }
        }
    
        @Override
        public void eraseCredentials() {
            super.eraseCredentials();
            this.credentials = null;
        }
    }
    

    自定义拦截类Filter,继承AbstractAuthenticationProcessingFilter

    import com.base.web.config.security.authentication.SmsAuthenticationToken;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
    import org.springframework.security.web.util.matcher.RequestMatcher;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * 自定义手机号、短信验证码登录过滤器
     *
     * @author ming
     * @version 1.0.0
     * @date 2021/3/1 15:17
     **/
    public class JwtSmsLoginFilter extends AbstractAuthenticationProcessingFilter {
    
        public JwtSmsLoginFilter(RequestMatcher requiresAuthenticationRequestMatcher) {
            super(requiresAuthenticationRequestMatcher);
        }
    
        @Override
        public void setAuthenticationManager(AuthenticationManager authenticationManager) {
            super.setAuthenticationManager(authenticationManager);
        }
    
        @Override
        public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
            String phoneNo = request.getParameter("phoneNo");
            String code = request.getParameter("code");
    
            if (phoneNo == null) {
                phoneNo = "";
            }
            if (code == null) {
                code = "";
            }
    
            SmsAuthenticationToken token = new SmsAuthenticationToken(phoneNo, code);
            //token.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));/
            token.setDetails(this.authenticationDetailsSource.buildDetails(request));
            SecurityContextHolder.getContext().setAuthentication(token);
    
            return super.getAuthenticationManager().authenticate(token);
        }
    
    }
    

    实现登录验证逻辑

    import cn.hutool.core.util.ObjectUtil;
    import com.base.common.constant.WebConstant;
    import com.base.redis.utils.RedisCacheUtil;
    import com.base.web.config.security.authentication.SmsAuthenticationToken;
    import com.base.web.service.AccountService;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.security.authentication.AuthenticationProvider;
    import org.springframework.security.authentication.BadCredentialsException;
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.stereotype.Component;
    
    import javax.annotation.Resource;
    import java.util.Collection;
    
    /**
     * 用户自定义身份认证, 短信验证码模式
     *
     * @author ming
     * @date : 2019/7/2 17:17
     * @since : 1.0
     */
    @Component
    public class SmsAuthenticationProvider implements AuthenticationProvider {
        @Resource
        private AccountService accountService;
        @Resource
        private RedisCacheUtil redisCacheUtil;
    
        /**
         * 认证处理,返回一个Authentication的实现类则代表认证成功,返回null则代表认证失败
         *
         * @date 2019/7/5 15:19
         * @since 1.0
         */
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            String phoneNo = authentication.getName();
            String code = (String) authentication.getCredentials();
            if (StringUtils.isBlank(phoneNo)) {
                throw new UsernameNotFoundException("手机号不可以为空");
            }
            if (StringUtils.isBlank(code)) {
                throw new BadCredentialsException("验证码不可以为空");
            }
            //验证短信验证码
            String key = phoneNo + WebConstant.REDIS_KEY_SUFFIX_FOR_VERIFICATION_CODE;
            boolean hasCode = redisCacheUtil.hasKey(key);
            if (!hasCode) {
                throw new BadCredentialsException("短信验证码已失效请重新获取");
            }
            String smsCode = redisCacheUtil.getString(key);
            //比较前端传入的明文和数据库中加密的密文是否相等
            if (!smsCode.equalsIgnoreCase(code)) {
                throw new BadCredentialsException("验证码错误");
            }
            redisCacheUtil.delete(key);
            //获取用户信息
            UserDetails user = accountService.loadUserByUsername(phoneNo);
            if (ObjectUtil.isEmpty(user)) {
                throw new BadCredentialsException("用户信息加载失败");
            }
    
            //获取用户权限信息
            Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
            return new UsernamePasswordAuthenticationToken(user, null, authorities);
        }
        
        /**
         * 如果该AuthenticationProvider支持传入的Authentication对象,则返回true
         *
         * @date 2019/7/5 15:19
         * @since 1.0
         */
        @Override
        public boolean supports(Class<?> aClass) {
    
            return SmsAuthenticationToken.class.isAssignableFrom(aClass);
        }
    }
    

    security配置

    // 添加过滤器
    http.addFilterBefore(smsLoginFilter(), AbstractPreAuthenticatedProcessingFilter.class);
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    	auth.userDetailsService(userService)
    			.passwordEncoder(passwordEncoder())
    			.and()
    			.authenticationProvider(smsAuthenticationProvider)
    			.authenticationProvider(passwordAuthenticationProvider);
    }
    
    /**
     * 登录认证器 --- 手机号、短信登录
     */
    @Bean
    public AbstractAuthenticationProcessingFilter smsLoginFilter() throws Exception {
    	JwtSmsLoginFilter jwtSmsLoginFilter = new JwtSmsLoginFilter(new AntPathRequestMatcher("/account/login", "POST"));
    	jwtSmsLoginFilter.setAuthenticationManager(this.authenticationManager());
    	jwtSmsLoginFilter.setAuthenticationSuccessHandler(authenticationSuccessHandler);
    	jwtSmsLoginFilter.setAuthenticationFailureHandler(authenticationFailureHandler);
    	return jwtSmsLoginFilter;
    }
    
    作者:jockming
    写博文不易,希望大家多多支持。评论一定一一回复
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    趣味网站、趣味应用
    趣味网站、趣味应用
    论文写作的句型
    Python Tricks(二十一)—— 排列组合的计算
    Python Tricks(二十一)—— 排列组合的计算
    辨异 —— 有两人生日在同一天、只有两人生日在同一天
    辨异 —— 有两人生日在同一天、只有两人生日在同一天
    品味电影
    品味电影
    HDU 4414 Finding crosses (DFS + BFS)
  • 原文地址:https://www.cnblogs.com/jockming/p/14849662.html
Copyright © 2011-2022 走看看