接口地址(官网)

image.png
可以使用http://gateway.zlt2000.cn/访问接口

权限接口

权限校验有两个步骤:授权和认证
image.png
除了OAuth2.0默认的四种授权方式,另外自定义实现了三种,分别是验证码授权、手机号、openId授权方式
image.png
image.png
image.png
因此,请求是否认证成功,需要通过js原生方法btoa()对”client_id:client_secret”进行base64的转码,添加到请求头的Authorization参数中
image.png
web端默认使用client_id=webApp,client_secret=webApp
grant_type的类型:

  • 密码模式:password
  • 授权码模式:authorization_code
  • 手机号授权:mobile_password
  • 验证码授权:password_code
  • openId授权:openId
  1. 使用aouth2.0密码模式获取token
    1. http://gateway.zlt2000.cn/api-uaa/oauth/token?grant_type=password&username=admin&password=admin
    image.png
    获取到token就可以使用接口文档请求接口了
    image.png
    登录成功调用获取用户信息和权限信息的接口,通过请求api-user/menus/current动态生成左侧菜单
    image.png
    image.png

SSO实现

OAuth2.0默认实现

@EnableOAuth2Sso + uaa授权中心 + Oauth授权码模式 实现了基于session的实现
自动通过认证过滤器实现了授权码认证
image.png

自定义授权码 + OAuth2.0实现

  1. 没有实现对登录的拦截,前端通过是否存在token判断登录状态,通过用户名密码登录,调用oauth/authorize?clientId=xxx获取code
  2. 增加了后端的API服务,通过api服务封装了授权码获取token的接口

image.png

  1. 前端记录访问地址,认证成功后重定向访问的地址

基于OIDC实现

OIDC协议(id_token) + OAuth2.0 + JWT(jwt格式封装access_token和id_token) + 非对称加密(解析id_token)
image.png

接口请求

自定义认证处理器和过滤器

  • 自定义token的解析和获取方式(headers/params)

    @Bean
    SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
      //认证处理器
      ReactiveAuthenticationManager customAuthenticationManager = new CustomAuthenticationManager(tokenStore);
      JsonAuthenticationEntryPoint entryPoint = new JsonAuthenticationEntryPoint();
      //token转换器
      ServerBearerTokenAuthenticationConverter tokenAuthenticationConverter = new ServerBearerTokenAuthenticationConverter();
      tokenAuthenticationConverter.setAllowUriQueryParameter(true);
      //oauth2认证过滤器
      AuthenticationWebFilter oauth2Filter = new AuthenticationWebFilter(customAuthenticationManager);
      oauth2Filter.setServerAuthenticationConverter(tokenAuthenticationConverter);
      oauth2Filter.setAuthenticationFailureHandler(new ServerAuthenticationEntryPointFailureHandler(entryPoint));
      oauth2Filter.setAuthenticationSuccessHandler(new Oauth2AuthSuccessHandler());
      http.addFilterAt(oauth2Filter, SecurityWebFiltersOrder.AUTHENTICATION);
    
      ServerHttpSecurity.AuthorizeExchangeSpec authorizeExchange = http.authorizeExchange();
      if (securityProperties.getAuth().getHttpUrls().length > 0) {
          authorizeExchange.pathMatchers(securityProperties.getAuth().getHttpUrls()).authenticated();
      }
      if (securityProperties.getIgnore().getUrls().length > 0) {
          authorizeExchange.pathMatchers(securityProperties.getIgnore().getUrls()).permitAll();
      }
      authorizeExchange
          .pathMatchers(HttpMethod.OPTIONS).permitAll()
          .anyExchange()
          .access(permissionAuthManager)
          .and()
          .exceptionHandling()
          .accessDeniedHandler(new JsonAccessDeniedHandler())
          .authenticationEntryPoint(entryPoint)
          .and()
          .headers()
          .frameOptions()
          .disable()
          .and()
          .httpBasic().disable()
          .csrf().disable();
      return http.build();
    }
    
    private String token(ServerHttpRequest request) {
      String authorizationHeaderToken = this.resolveFromAuthorizationHeader(request.getHeaders());
      String parameterToken = (String)request.getQueryParams().getFirst("access_token");
      if (authorizationHeaderToken != null) {
        if (parameterToken != null) {
          BearerTokenError error = BearerTokenErrors.invalidRequest("Found multiple bearer tokens in the request");
          throw new OAuth2AuthenticationException(error);
        } else {
          return authorizationHeaderToken;
        }
      } else {
        return parameterToken != null && this.isParameterTokenSupportedForRequest(request) ? parameterToken : null;
      }
    }
    

    单点登出

    image.png