No2.搭建基本的资源端解析token(资源服务端)
代码地址与接口看总目录:【学习笔记】记录冷冷-pig项目的学习过程,大概包括Authorization Server、springcloud、Mybatis Plus~~~_清晨敲代码的博客-CSDN博客
目录
A1.框架搭建
A2.代码实现
B1.配置类
B2.accesstoken认证核心类
B3.端点类
首先,请求接口时只携带并解析accesstoken,使用授权服务端默认的OAuth2TokenIntrospectionEndpointFilter过滤器,无用户持久化操作,仅认证无鉴权;
仅作为最基本的资源服务端。
注意:授权服务端、资源服务端、客户端:我的理解是,
资源服务器是跟随授权服务端搭建的,可以和授权服务共属于同一个系统环境下,例如数据库可共用、公共包可共用。
而第三方客户端大多不是,第三方客户端大多和授权服务器无任何关系,只是通过授权联系起来,客户端应该有自己的一套认证与权限,例如我们开发一个系统,其中可以使用gitee认证登录时,我们的系统和gitee是没有任何关系的,只是能够通过gitee的用户授权拿到gitee的accesstoken然后并携带着访问gitee公开的接口而已。
A1.框架搭建
按照pig项目框架搭建即可,当前需要的都有是:
“#”符号表示重点的包名
com.pig4cloud.pig
├── pig-common // 框架核心模块
│ └── pig-common-bom // 定义common全局jar版本模块
│ └── pig-common-common // 公共工具类核心模块
│ └── # constant // 公共常量包
│ └── # util // 公共工具包
│ └── pig-common-security // 安全工具模块
│ └── # annotation // 安全注解包
│ └── # component // 安全组件包,包括配置等
│ └── # util // 安全工具包
├── pig-upms // 通用用户权限管理聚合模块
│ └── pig-upms-api // 通用用户权限管理系统公共api模块
│ └── pig-upms-biz // 通用用户权限管理系统业务处理模块
│ └── # controller // 业务端点包
现在主要就是pig-auth包实现核心代码
A2.代码实现
最重要会涉及到一个过滤器:BearerTokenAuthenticationFilter(进行accesstoken认证)
整体流程是,拿到accesstoken,然后向授权服务器获取到授权信息(包括用户信息),拿到后可以选择根据授权信息和用户信息确认UserDetails(这里的确认是从持久层中确认),然后封装成BearerTokenAuthentication并存到SecurityContextHolder里面,然后执行后面filter。
注意:
授权服务端会提供一个默认的OAuth2TokenIntrospectionEndpointFilter过滤器来拦截“/oauth2/introspect”令牌自省端点,在这个过滤器中校验后并返回授权信息。
默认该端点是需要认证权限的,可以设置端点权限为permit。
如果是要认证那么需要资源服务端提供客户端信息(Basic/POST/其他方式),然后会在授权服务端的OAuth2ClientAuthenticationFilter里面拿到并认证,之后才会顺利通过FilterSecurityInterceptor过滤器,进入OAuth2TokenIntrospectionEndpointFilter。
所以整体逻辑是,先写配置类,想好都需要哪些自定义类,先将配置文件补充完整,然后在去补充自定义代码逻辑。
1.配置类和自定义accesstoken认证类都可以写到统一的安全模块;
2.授权服务端需要提供通过accesstoken拿到授权信息接口;
3.资源服务端提供资源接口;
B1.配置类
C1.PigResourceServerConfiguration
@Configuration
//@EnableWebSecurity
@RequiredArgsConstructor
public class PigResourceServerConfiguration {
private final PermitAllUrlProperties permitAllUrlProperties;
private final BearerTokenResolver pigBearerTokenExtractor;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
//配置端点白名单方放行
//配置资源服务信息
//配置accesstoken提取器
//配置token自省器
//忽略掉相关端点的 csrf
return http.build();
}
}
C2.PigResourceServerAutoConfiguration
@RequiredArgsConstructor
@EnableConfigurationProperties(PermitAllUrlProperties.class)
public class PigResourceServerAutoConfiguration {
/**
* @Description: 请求令牌的提取逻辑
* @param urlProperties 对外暴露的接口列表
* @Return: com.pig4cloud.pig.common.security.component.PigBearerTokenExtractor
*/
@Bean
public PigBearerTokenExtractor pigBearerTokenExtractor(PermitAllUrlProperties urlProperties) {
//new一个请求令牌的提取逻辑器
return new PigBearerTokenExtractor(urlProperties);
}
}
C3.@EnablePigResourceServer
这个是资源服务器注解,由于资源服务器可能会有多个,而且其中的安全配置有大多相同,所以可以在security公共安全包里编写一个配置类,然后通过注解添加到各个资源服务器中进行使用,这样更方便
@Documented
@Inherited //@Inherited修饰的注解的@Retention是RetentionPolicy.RUNTIME,则增强了继承性,在反射中可以获取得到
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Import({PigResourceServerConfiguration.class, PigResourceServerAutoConfiguration.class})
public @interface EnablePigResourceServer {
}
B2.accesstoken认证核心类
C1.PigBearerTokenExtractor
BearerTokenResolver的功能主要是拿到请求里的accesstoken,为什么要自定义一个类实现BearerTokenResolver呢?默认提供的DefaultBearerTokenResolver,有正则匹配的类型("^Bearer (?<token>[a-zA-Z0-9-._~+/]+=*)$"
),而现在用的accesstoken的形式是Bearer clientId::username::UUID,不能匹配上,需要稍加改造,并且我们可以再添加多个类型的校验,防止伪造。
public class PigBearerTokenExtractor implements BearerTokenResolver {
@Override
public String resolve(HttpServletRequest request) {
//校验请求路径,是白名单直接返回null
//校验hearder里的accesstoken格式是否匹配,并返回token
//校验请求方式是否是GET/POST,是就从参数中获取accesstoken,并返回token
//判断如果headertoekn不是空
//如果parametertoekn不是空则抛出多个accesstoken异常
//如果parametertoekn是空则返回headertoekn
//如果parametertoekn不是空并且支持参数的token,则返回parameteken
//都是空则返回null
return null;
}
}
C2.OpaqueTokenIntrospector
携带token去授权服务端获取对应的有效用户信息,可以使用默认的实现类SpringOpaqueTokenIntrospector或者NimbusOpaqueTokenIntrospector(使用这个类需要引入<artifactId>oauth2-oidc-sdk</artifactId>
)
这两个类,都会在携带token的基础上携带BasicAuthentication,去访问授权服务端的令牌自行端点。端点和客户端信息是在PigResourceServerConfiguration里面配置的哦。
如果想自定义该类并且不想携带客户端信息,可以去授权服务端,设置“/oauth2/introspect”端点权访问权限为permit。
B3.端点类
C1.AuthenticatedController
访问权限是 authenticated 的权限,可以获取到SecurityContextHolder.getContext().getAuthentication()
C2.PermitController
访问权限是permit的权限