• springcloud +spring security多种验证方式之第三方token生成自己的token通过校验和自己的表单验证大体流程


    步骤:

      1.继承 WebSecurityConfigurerAdapter.class,其中使用两个过滤器,一个spring scurity自带的UsernamePasswordAuthenticationFilter,一个是自定义的过滤器ZTSSOAuthenticationProcessingFilter ,他们都继承AbstractAuthenticationProcessingFilter,该filter的功能是去指定拦截界面发送的post请求,然后加入到filter chain 中去。

    import com.idoipo.ibt.service.LoginAuthenticationSuccessHandler;
    import com.idoipo.ibt.service.SmsAuthenticationProvider;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
    import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
    
    /**
     * Created by pingli on 2018-10-13.
     */
    @Configuration
    @EnableWebSecurity
    @SuppressWarnings("unused")
    public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter{
    
        @Value("${com.cookie}")
        private String sessionCookieName;
    
        @Value("${com..cookie.token}")
        private String tokenCookie;
    
        @Value("${com.cookie.timer}")
        private String timerCookie;
    
        @Value("${com.cookie.curp}")
        private String curpCookie;
    
        @Value("${com.cookie.gw}")
        private String gwCookie;
    
        @Value("${com.cookie.commondomain}")
        private String cdCookie;
    
        @Value("${com.index}")
        private String homeUrl;
        @Value("${com.main}")
        private String mainUrl;
        @Value("${zt.ssoUrl}")
        private String ssoUrl;
        @Value("${zt.appId}")
        private String appId;
    
        @Value("${com.idoipo.infras.ibt}")
        private String ibtUrl;
    
    
        @Autowired
        private SmsAuthenticationProvider authenticationProvider;
    
        @Autowired
        private ZTSSOAuthenticationProvider ztssoAuthenticationProvider;
    
        @Autowired
        @Qualifier("authenticationManagerBean")
        private AuthenticationManager authenticationManager;
    
        @Autowired
        private LoginAuthenticationSuccessHandler successHandler;
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            String logoutUrl="/logout";
            String loginUrl="/login";
            String loginMiddleUrl="/SsoLogin";
            String ssoUrlRequest = ssoUrl+"?a="+appId+"&"+"r="+ibtUrl+loginMiddleUrl;
            http.formLogin()//处理登录
                    .loginPage(ssoUrlRequest)
                    .successHandler(successHandler)
                    .loginProcessingUrl(loginUrl)
                    .usernameParameter("mobile")
                    .passwordParameter("check")
                    .failureUrl(ssoUrlRequest)
                    .permitAll()
                    .and()
                .authorizeRequests()//请求授权
                    .antMatchers("/",homeUrl,"/file/supload","/dist/**",loginMiddleUrl).permitAll()//首页与前端资源可以直接访问
                    .antMatchers(logoutUrl,"/heartbeat").authenticated()
                    .antMatchers(loginUrl).anonymous()
                    .anyRequest().authenticated()
                    .and()
                .logout()
                    .logoutUrl(logoutUrl)
                    .logoutSuccessUrl(homeUrl)
                    .invalidateHttpSession(true)
                    .deleteCookies(sessionCookieName,tokenCookie,timerCookie,curpCookie,gwCookie,cdCookie)
                    .logoutRequestMatcher(new AntPathRequestMatcher(logoutUrl, "GET"))
                    .and()
                .csrf()
                    .disable()
                .addFilterAt(ztssoAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class);//增加过滤/SsoLogin接口请求
        }
    
    
        @Bean
        public ZTSSOAuthenticationProcessingFilter ztssoAuthenticationFilter() {
            ZTSSOAuthenticationProcessingFilter filter = new ZTSSOAuthenticationProcessingFilter();
            filter.setAuthenticationManager(authenticationManager);
            filter.setAuthenticationSuccessHandler(successHandler);
            return filter;
        }
    
        @Override
        @Bean
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.authenticationProvider(this.authenticationProvider)
            .authenticationProvider(this.ztssoAuthenticationProvider);
    
        }
    
    
    }
    import com.idoipo.ibt.controllers.HomeController;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.security.authentication.AbstractAuthenticationToken;
    import org.springframework.security.authentication.AuthenticationServiceException;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
    import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    /**
     * Created by pingli on 2018-10-06
     * 拦截请求
     */
    public class ZTSSOAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {
    
        private Logger logger = LoggerFactory.getLogger(ZTSSOAuthenticationProcessingFilter.class);
        public static final String SPRING_SECURITY_FORM_ZT_TOKEN = "Token";
    
        private String ZTToken = SPRING_SECURITY_FORM_ZT_TOKEN;
        private boolean postOnly = true;
    
        public ZTSSOAuthenticationProcessingFilter() {
    
            super(new AntPathRequestMatcher("/SsoLogin", "POST"));
        }
    
        @Override
        public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
                throws AuthenticationException {
            logger.info("进入sso过滤器");
            if (postOnly && !request.getMethod().equals("POST")) {
                throw new AuthenticationServiceException(
                        "Authentication method not supported: " + request.getMethod());
            }
    
            String token = obtainToken(request);
    
            if (token == null) {
                token = "";
            }
    
            AbstractAuthenticationToken authRequest = new ZTSSOAuthenticationToken(null,token);
    
            // Allow subclasses to set the "details" property
            setDetails(request, authRequest);
    
            return this.getAuthenticationManager().authenticate(authRequest);
        }
    
    
        protected String obtainToken(HttpServletRequest request) {
            return request.getParameter(ZTToken);
        }
    
        protected void setDetails(HttpServletRequest request,
                                  AbstractAuthenticationToken authRequest) {
            authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
        }
    
    }

    2

    ZTSSOAuthenticationProcessingFilter 拦截到SsoLogin 的post请求后,需要一个继承
    AbstractAuthenticationToken的token类来存得到的第三方的token参数。
    import org.springframework.security.authentication.AbstractAuthenticationToken;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.SpringSecurityCoreVersion;
    
    import java.util.Collection;
    
    /**
     * Created by pingli on 2018-10-06
     * 生成登录session,同用户不用再校验
     */
    public class ZTSSOAuthenticationToken extends AbstractAuthenticationToken {
    
        private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
    
        private final Object principal;
        private String credentials;
    
        public ZTSSOAuthenticationToken(Object principal,String credentials) {
            super(null);
            this.principal = principal;
            this.credentials = credentials;
            super.setAuthenticated(true);
        }
    
        public ZTSSOAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) {
            super(authorities);
            this.principal = principal;
            this.credentials = null;
            super.setAuthenticated(true); // must use super, as we override
        }
    
        // ~ Methods
        // ========================================================================================================
    
        public String getCredentials() {
            return this.credentials;
        }
    
        public Object getPrincipal() {
            return this.principal;
        }
    
        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");
            }
    
            super.setAuthenticated(false);
        }
    
        @Override
        public void eraseCredentials() {
            super.eraseCredentials();
            credentials = null;
        }
    
    }

    3.得到参数后,需要根据token,去第三方查询用户信息,用户生成自己系统的token,这一步在实现了

    AuthenticationProvider的类中去处理,这个类需要去指定
    ZTSSOAuthenticationToken 支持他,所以需要重写
    supports方法,从而关联上ZTSSOAuthenticationProcessingFilter ,
    ZTSSOAuthenticationToken ,
    AuthenticationProvider这三个类,filter得到请求,token去保存参数,provider去获取支持的token类的参数,从而完成一条线,后续其他验证也可以采用该种方式去增加,注意如果要增加成功后的处理,请注意
    继承了WebSecurityConfigurerAdapter中添加
    filter.setAuthenticationSuccessHandler(successHandler);去设置授权成功后可以进行一些后续处理,比如生成token字符串到前台,或者指定默认的跳转路径
    import com.idoipo.ibt.bto.AccountInfo;
    import com.idoipo.ibt.bto.UserDetail;
    import com.idoipo.ibt.service.UserService;
    import org.apache.commons.lang.StringUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.authentication.AuthenticationProvider;
    import org.springframework.security.authentication.BadCredentialsException;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.stereotype.Component;
    
    /**
     * Created by pingli on 2018-10-06
     * sso验证类
     */
    @Component
    public class ZTSSOAuthenticationProvider implements AuthenticationProvider {
    
        private Logger logger= LoggerFactory.getLogger(ZTSSOAuthenticationProvider.class);
        @Autowired
        private UserService userService;
    
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            String ZTToken = (authentication.getCredentials()==null)?null:authentication.getCredentials().toString();
            if (StringUtils.isEmpty(ZTToken)) {
                throw new BadCredentialsException("token不能为空");
            }
            AccountInfo accountInfo = userService.getUserInfoBySSO(ZTToken);
            logger.info("当前sso反回账号信息={}",accountInfo);
            UserDetail userDetail  = userService.getTokenByPsnId(accountInfo.getAccount());
            ZTSSOAuthenticationToken result = new ZTSSOAuthenticationToken(userDetail,userDetail.getJwtToken());
            result.setDetails(authentication.getDetails());
            return result;
        }
    
        @Override
        public boolean supports(Class<?> authentication) {
            logger.info(this.getClass().getName() + "---supports");
            return (ZTSSOAuthenticationToken.class.isAssignableFrom(authentication));
        }
    
        //后续权限控制
    //    private Set<GrantedAuthority> listUserGrantedAuthorities(Long uid) {
    //        Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
    //        if (null == uid) {
    //            return authorities;
    //        }
    //        authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
    //        return authorities;
    //    }
    
    }
    import com.idoipo.ibt.bto.UserDetail;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
    import org.springframework.stereotype.Component;
    import org.springframework.util.StringUtils;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.Arrays;
    import java.util.List;
    
    /**
     * Created by Jemmy on 2017-09-08.
     */
    @Component
    @SuppressWarnings("unused")
    public class LoginAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler{
    
        private Logger logger= LoggerFactory.getLogger(LoginAuthenticationSuccessHandler.class);
    
        @Value("${com.pages.main}")
        private String mainUrl;
    
        @Value("${com.common.domain}")
        private String commonDomain;
    
        public LoginAuthenticationSuccessHandler() {
            super();
        }
    
        @Override
        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {
    
    
            logger.info("登录用户服务成功");
            this.setDefaultTargetUrl(mainUrl);
            this.setAlwaysUseDefaultTargetUrl(true);
            UserDetail userDetail=(UserDetail)authentication.getPrincipal();
           // request.setAttribute("TOKEN",userDetail.getJwtToken());
            Cookie cookie=new Cookie("IBT-TOKEN",userDetail.getJwtToken());
            cookie.setPath("/");
            cookie.setHttpOnly(false);
            cookie.setDomain(commonDomain);
            response.addCookie(cookie);
            super.onAuthenticationSuccess(request, response, authentication);
            //request.getRequestDispatcher("redirect:/main").forward(request,response);
    
        }
    }
  • 相关阅读:
    简单的Servlet结合Jsp实现请求和响应以及对doGet和doPost的浅析
    My1stServlet
    Myeclipse发布第一个jsp页面及web project部署到tomcat上的几种方法
    java中循环的不同终止方式
    Mybatis学习笔记
    python 进程间的数据交互
    python 进程
    python 队列
    python 多线程
    python paramiko 向linux执行命令和发送接收文件
  • 原文地址:https://www.cnblogs.com/keepMoveForevery/p/9776997.html
Copyright © 2020-2023  润新知