首頁 > 軟體

SpringSecurity微服務實戰之公共模組詳解

2022-08-26 18:05:40

前言

在專案中安全框架是必不可少的,在微服務架構中更是尤為重要,我們專案中將安全模組單獨抽離了一個公共模組出來,因為在我的專案架構中 需要用到的SpringSecurity 至少有三個地方 boss服務 admin服務 user服務(saas)模式的一個微服務架構

模組結構

主要分為 base服務(提供資料,可以部署多份進行負載均衡) boss模組 admin模組 gateway模組 以及公共模組其中就包含我們今天的主角 安全模組。

我們在TokenLoginFilter中繼承 AbstractAuthenticationProcessingFilter抽象類 重寫 attemptAuthentication方法 在裡面分別指定驗證器

@Override
public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException {
    if (!httpServletRequest.getMethod().equals("POST")) {
        throw new AuthenticationServiceException(
                "Authentication method not supported: " + httpServletRequest.getMethod());
    }
    User user = new ObjectMapper().readValue( httpServletRequest.getInputStream(), User.class);
    //處理驗證碼
    AbstractAuthenticationToken authRequest = null;
    switch(user.getType()) {
        //租戶登入
        case "1":
            authRequest = new TenantAuthenticationToken(user.getUsername(), user.getPassword());
            break;
        //平臺登入
        case "2":
            authRequest = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
            break;
    }
    setDetails(httpServletRequest, authRequest);
    return this.getAuthenticationManager().authenticate(authRequest);
}

其中TenantDetailsAuthenticationProvider租戶驗證器(admin) 和UsernamePasswordAuthenticationProvider 平臺驗證器(boss)

這裡當然還可以再加其他的驗證器,比如後面如果還有app的話就可以在設定一個專門來做app端許可權驗證的驗證器。

下面我們看看令牌的續期是怎麼實現的: 令牌是由jwt生成 和 redis 配合使用,每一次親求進來檢查token是否合法的同時校驗一下token的剩餘時間是否大於一個閾值,如果小於閾值我們進行reids 中的令牌重新整理時間讓使用者無感知續約。

/**
 * 驗證令牌有效期,相差不足20分鐘,自動重新整理快取
 * @param loginUser
 * @return 令牌
 */
public void verifyToken(OnlineUserInfo loginUser,Integer type)
{
    long expireTime = loginUser.getExpireTime();
    long currentTime = System.currentTimeMillis();
     long chazhu= expireTime - currentTime;
    if (chazhu <= MILLIS_MINUTE_TEN)
    {
        refreshToken(loginUser,type);
    }
}

在存取過濾器中進行校驗就可以了,這樣就可以做到使用者無感知令牌續約。

安全驗證模組目前是再每個服務上面引入使用,後面會考慮在閘道器層做鑑權處理。

最後貼一下 WebSecurityConfigBugVip 這個設定類

@Configuration
@EnableWebSecurity
public class WebSecurityConfigBugVip extends WebSecurityConfigurerAdapter {
    private TokenManager tokenManager;
    @Autowired
    private TenantDetailsAuthenticationProvider userDetailsAuthenticationProvider;
    @Autowired
    private UsernamePasswordAuthenticationProvider usernamePasswordAuthenticationProvider;
    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;
    /**
     * 裝配自定義的Provider
     * @param auth
     */
    @Override
    public void configure(AuthenticationManagerBuilder auth){
        auth.authenticationProvider(userDetailsAuthenticationProvider);//將我們自定義的認證器設定進來
        auth.authenticationProvider(usernamePasswordAuthenticationProvider);//預設的認證器
    }
    @Autowired
    public WebSecurityConfigBugVip(TokenManager tokenManager, RedisTemplate redisTemplate) {
        this.tokenManager = tokenManager;
        this.redisTemplate = redisTemplate;
    }
    /**
     * 設定設定
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.exceptionHandling()
                .authenticationEntryPoint(new UnauthorizedEntryPoint())
                .and().csrf().disable()
                .addFilterAt(tokenLoginFilter(), UsernamePasswordAuthenticationFilter.class)
                .authorizeRequests()//設定需要放行的請求
                .antMatchers("/swagger-ui.html/**","/v2/**","/webjars/**","/swagger-resources/**","/boss/verifi/getCode","/boss/verifi/checkVrrifyCode","/boss/sysuser/write","/boss/sysuser/read").permitAll()
                .anyRequest().authenticated()
                .and().logout().logoutUrl("/boss/acl/logout")
                .and().logout().logoutUrl("/admin/acl/logout")
                .addLogoutHandler(new TokenLogoutHandler(tokenManager, redisTemplate)).and()
                .addFilter(new TokenAuthenticationFilter(authenticationManager(), tokenManager, redisTemplate)).httpBasic();//設定存取過濾器
    }
    /**
    *token過濾器
    */
    @Bean
    public TokenLoginFilter tokenLoginFilter() {
        TokenLoginFilter filter = new TokenLoginFilter();
        filter.setAuthenticationManager(authenticationManager);
        return filter;
    }
    /**
     * 處理注入 AuthenticationManager失敗問題
     * @return
     * @throws Exception
     */
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

以上就是SpringSecurity微服務實戰之公共模組詳解的詳細內容,更多關於SpringSecurity微服務公共模組的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com