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);

    }
}
原文地址:https://www.cnblogs.com/keepMoveForevery/p/9776997.html