02-配置基于OAuth2协议的认证授权

OAuth2协议

协议中的角色

OAUTH协议为用户资源的授权提供了一个安全开放而又简易的标准,任何第三方都可以使用OAUTH认证服务,任何服务提供商都可以实现自身的OAUTH认证服务

02-配置基于OAuth2协议的认证授权_第1张图片

OAuth协议目前发展到2.0版本并得到广泛应用(1.0版本过于复杂),微信扫码认证就是一种基于OAuth2协议实现的第三方认证方式

  • 微信扫码的目的是通过微信认证登录目标网站,目标网站需要从微信获取当前用户的身份信息才会让当前用户在目标网站登录成功
  • 用户点击微信打开扫码界面, 然后扫描微信二维码请求微信服务端进行认证,认证通过后微信会向用户返回等待的授权页面即是否确认登陆
  • 用户如果点击确认登陆表示授权目标网站去微信服务端获取自己微信服务器中保存的信息,微信认证服务器会颁发一个授权码给目标网站
  • 目标网站携带微信颁发的授权码请求微信认证服务器颁发令牌,微信认证服务器收到请求后向目标网站响应令牌(此交互过程用户看不到)
  • 目标网站携带令牌请求微信服务器获取用户的基本信息,对应的微信资源服务器向目标网站返回用户的信息
  • 目标网站接收到用户信息,此时用户就在目标网站登录成功,可以正常访问目标系统内的资源

02-配置基于OAuth2协议的认证授权_第2张图片

协议的应用

OAuth2是一个标准的开放的授权协议,应用程序可以根据自己的需求去使用

  • 当学成在线访问第三方系统的资源时需要接入微信扫码登录,基于OAuth2协议访问微信服务端中的用户信息
  • 当第三方系统想要访问学成在线网站的资源时也可以基于OAuth2协议访问学成在线认证服务中的用户信息
  • 当学成在线前端页面即客户端访问学成在线微服务的资源时也可以基于OAuth2协议

02-配置基于OAuth2协议的认证授权_第3张图片

OAuth2的授权模式

Spring Security支持OAuth2认证,OAuth2提供授权码模式(微信扫描)、密码模式、简化模式(了解)、客户端模式(了解 )等四种授权模式

  • 授权码模式: 适合客户端和第三方系统的认证服务在非同一个系统的情况,所以本项目采用授权码模式完成微信扫码认证
  • 密码模式: 适用于认证服务系统是我们自己开发的情况下,所以本项目采用密码模式作为前端请求微服务的认证方式

OAuth2中不同的授权模式对应不同的获取令牌的方式,最终目的都是从获取认证服务颁发的令牌,然后通过令牌去获取资源

  • 获取令牌首先要获取授权码,而授权码的获取需要资源拥有者亲自授权同意才可以获取

02-配置基于OAuth2协议的认证授权_第4张图片

配置步骤

第一步: 在xuecheng-plus-auth工程的config包下配置基于OAuth2.0的认证授权服务,包含AuthorizationServer(颁发授权码)TokenConfig(颁发令牌)

第二步: 创建AuthorizationServer配置类继承AuthorizationServerConfigurerAdapter并重写方法,然后使用@EnableAuthorizationServer注解标识

功能
AuthorizationServerSecurityConfigurer 用来配置令牌端点的安全约束
ClientDetailsServiceConfigurer 用来配置客户端详情服务,如客户端的Id和密钥(明文或BCrypt格式格式)
并不是随便一个客户端都可以接入到系统的认证服务中,认证服务提供商会给批准接入的客户端一个身份用于接入时凭据,包含客户端的标识和秘钥
我们想要接入微信的认证服务就需要一个凭据
AuthorizationServerEndpointsConfigurer 用来配置令牌的访问端点和令牌服务
@Configuration
@EnableAuthorizationServer
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {
    @Resource(name="authorizationServerTokenServicesCustom")
    private AuthorizationServerTokenServices authorizationServerTokenServices;
    @Autowired
    private AuthenticationManager authenticationManager;
    // 客户端详情服务
    @Override
    public void configure(ClientDetailsServiceConfigurer clients)
        throws Exception {
        clients.inMemory()// 使用inmemory存储客户端的详情信息
            .withClient("XcWebApp")// 客户端Id
            // 客户端密钥基于明文的方式
            .secret("XcWebApp")
            // 客户端密钥基于BCrypt格式
            .secret(new BCryptPasswordEncoder().encode("XcWebApp"))
            .resourceIds("xuecheng-plus") //资源列表
            // 认证服务允许的授权类型即客户端申请令牌的方式
			.authorizedGrantTypes("authorization_code", "password","client_credentials","implicit","refresh_token")            					// 允许的授权范围
            .scopes("all")
            // false表示跳转到授权页面
            .autoApprove(false)
            // 客户端接收授权码时重定向的地址
            .redirectUris("http://www.51xuecheng.cn");
    }
    // 令牌端点的访问配置
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints
            .authenticationManager(authenticationManager)//认证管理器
            .tokenServices(authorizationServerTokenServices)//令牌管理服务
            .allowedTokenEndpointRequestMethods(HttpMethod.POST);
    }

    // 令牌端点的安全配置
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security){
        security
            .tokenKeyAccess("permitAll()") //oauth/token_key是公开
            .checkTokenAccess("permitAll()")//oauth/check_token公开
            .allowFormAuthenticationForClients();//表单认证(申请令牌)
            
    }
}

第三步:创建TokenConfig配置类配置令牌的相关策略,使用InMemoryTokenStore在内存存储令牌

@Configuration
public class TokenConfig {
    @Autowired
    TokenStore tokenStore;
    @Bean
    public TokenStore tokenStore() {
        // 在内存中存储令牌,这种令牌是普通令牌
        return new InMemoryTokenStore();
    }
    @Bean(name = "authorizationServerTokenServicesCustom")
    public AuthorizationServerTokenServices tokenService() {
        DefaultTokenServices service = new DefaultTokenServices();
        service.setSupportRefreshToken(true);//支持刷新令牌
        service.setTokenStore(tokenStore);//令牌存储策略
        service.setAccessTokenValiditySeconds(7200); //令牌默认有效期2小时
        service.setRefreshTokenValiditySeconds(259200); //刷新令牌默认有效期3天
        return service;
    }
}

第四步: 在config/WebSecurityConfig中配置负责认证管理的Bean

@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    ···
}

测试授权码模式

第一步: 重启认证服务,先登陆账号然后发送Get请求获取授权码,认证服务颁发的授权码使用一次后就无效了,需要重新申请,请求参数取决于AuthorizationServer配置类中配置的信息

  • 授权码模式就是使用授权码去获取令牌,所以首先要获取授权码,授权码的获取需要资源拥有者亲自授权同意才可以获取
  • 获取授权码: http://localhost:63070/auth/oauth/authorize?client_id=XcWebApp&response_type=code&scope=all&redirect_uri=http://localhost/

02-配置基于OAuth2协议的认证授权_第5张图片

请求参数 描述
client_id 客户端准入标志
response_type 对于授权码模式固定为code
scope 客户端权限
redirect_uri 当授权码申请成功后门会跳转到此地址并在后面带上code=授权码,如http://localhost/?code=H7J61Z

第二步: 携带认证服务端响应的授权码发送Post请求申请令牌,相关请求参数取决于AuthorizationServer中配置的客户端详情服务

  • 申请令牌:http://localhost:63070/auth/oauth/token?client_id=XcWebApp&client_secret=XcWebApp&grant_type=authorization_code&code=H7J61Z&redirect_uri=http://localhost/
请求参数 描述
client_id 客户端准入标识
client_secret 客户端秘钥
grant_type 授权类型,authorization_code表示授权码模式,需要在AuthorizationServer中配置
code 认证服务端响应的授权码
redirect_uri 当令牌申请成功后门会跳转到此地址,和申请授权码时使用的redirect_uri一致

第三步: 查看认证服务端响应的令牌

响应参数 描述
access_token 令牌用于访问资源使用
token_type bearer是在RFC6750中定义的一种token类型,在携带令牌访问资源时需要在head中加入bearer 令牌内容(空格分开)
refresh_token 当令牌快过期时使用刷新令牌,可以再次生成令牌
expires_in 过期时间
scope 令牌的权限范围,服务端可以根据令牌的权限范围去对令牌授权
// 携带授权码获取令牌
POST {{auth_host}}/auth/oauth/token?client_id=XcWebApp&client_secret=XcWebApp&grant_type=authorization_code&code=H7J61Z&redirect_uri=http://localhost/

// 申请令牌成功如下所示
{
"access_token": "c75d121f-7430-4cf9-9ff6-eb25e5c01ca0",
"token_type": "bearer",
"refresh_token": "b950149e-40e8-47f3-9f1d-1c6df74dd69f",
"expires_in": 7199,
"scope": "all"
}

测试密码模式

授权码模式需要借助浏览器供用户亲自授权, 而密码模式较简单不用借助浏览器,但是却直接将用户的敏感信息泄露给了客户端

  • 客户端直接携带用户的账号和密码去认证服务端申请令牌

02-配置基于OAuth2协议的认证授权_第6张图片

第一步: 直接发送Post请求携带客户端的Id和密钥以及用户的账号和密码等请求参数访问xuecheng-plus-auth工程的认证服务获取令牌

POST {{auth_host}}/auth/oauth/token?client_id=XcWebApp&client_secret=XcWebApp&grant_type=password&username=Kyle&password=123
请求参数
client_id 客户端准入标识
client_secret 客户端秘钥
grant_type 授权类型,填写password标识密码模式
username 资源拥有者用户名
password 资源拥有者密码

第二步: 查看服务端响应的令牌

{
"access_token": "c75d121f-7430-4cf9-9ff6-eb25e5c01ca0",
"token_type": "bearer",
"refresh_token": "b950149e-40e8-47f3-9f1d-1c6df74dd69f",
"expires_in": 4687,
"scope": "all"
}

你可能感兴趣的:(#,Spring,Security,OAuth2协议,Spring,Security)