好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

SpringSecurity微服务实战之公共模块详解

前言

在项目中安全框架是必不可少的,在微服务架构中更是尤为重要,我们项目中将安全模块单独抽离了一个公共模块出来,因为在我的项目架构中 需要用到的SpringSecurity 至少有三个地方 boss服务 admin服务 user服务(saas)模式的一个微服务架构

模块结构

主要分为 base服务(提供数据,可以部署多份进行负载均衡) boss模块 admin模块 gateway模块 以及公共模块其中就包含我们今天的主角 安全模块。

我们在 TokenLoginFilter 中继承 AbstractAuthenticationProcessingFilter 抽象类 重写 attemptAuthentication方法 在里面分别指定验证器

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

@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 中的令牌刷新时间让用户无感知续约。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

/**

  * 验证令牌有效期,相差不足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 这个配置类

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

@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微服务公共模块的资料请关注其它相关文章!

原文链接:https://juejin.cn/post/7135603061614968869

查看更多关于SpringSecurity微服务实战之公共模块详解的详细内容...

  阅读:25次