springcloud +spring security多種驗證方式之第三方token生成本身的token經過校驗和本身的表單驗證大致流程

步驟:前端

  1.繼承 WebSecurityConfigurerAdapter.class,其中使用兩個過濾器,一個spring scurity自帶的UsernamePasswordAuthenticationFilter,一個是自定義的過濾器ZTSSOAuthenticationProcessingFilter ,他們都繼承AbstractAuthenticationProcessingFilter,該filter的功能是去指定攔截界面發送的post請求,而後加入到filter chain 中去。java

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

}

2web

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,這一步在實現了spring

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

    }
}
相關文章
相關標籤/搜索