SpringSecurity学习笔记之 入门 七 (oauth2.0整合【Security实现oauth2.0】)

授权码模式:

1.需要提供appid和app密码
2.配置回调地址
3.验证token接口


实现流程:
1.引入必要依赖:

security
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
oauth2
<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
    <version>2.2.1.RELEASE</version>
</dependency>
jwt
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

2.修改security配置
完成这个部分(拦截+用户校验部分)

新增授权类AuthorizationConfig 继承AuthorizationServerConfigurerAdapter
重写他的两个配置方法,
在类中注入我们配置好的加密类:

@Component
@EnableAuthorizationServer
public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter{
	@Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    }
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    }
}

AuthorizationServerSecurityConfigurer 参数的方法中配置允许表单提交

 @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients().checkTokenAccess("permitAll()");
    }

ClientDetailsServiceConfigurer参数的方法中配置

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    clients.inMemory()
            //appid
            .withClient("gaga")
            //appsecret
            .secret(passwordEncoder.encode("gaga_test_security"))
            //授权码
            .authorizedGrantTypes("authorization_code")
            //作用域
            .scopes("all")
            //资源id
            .resourceIds("employed_resource")
            //回调地址
            .redirectUris("127.0.0.1:18001/callback");
}

在实际开发中我们会将这些数据储存于DB,当后端认证通过以后执行这个方法的时候我们动态的查询数据库,将信息写入,类似权限添加部分;
这就完成了;

认证:
当我们访问

http://127.0.0.1:18001/oauth/authorize?client_id=employed&response_type=code


client_id写上自己的appid,type=code;

  1. 当我们访问的时候如果没有登录会提示我们登录;当我们登录成功后就会提示我们是否愿意让上面我们配置的appid的客户端获取我们的数据信息
  2. 当点击同意获取的时候,页面就会重定向到我们指定的回调函数,并且后面附带一个参数,授权码;
  3. 这时候我们后台就能通过回调地址获取到授权码,根据授权码生成Token
  4. 根据授权码获取acccessToken;访问:http://127.0.0.1:18001/oauth/token?code=授权码&grant_type=authorization_code&redirect_url=http://127.0.0.1:18001/callback&scope=all对应我们配置中的每一条配置;
  5. 这时候又会让我们登录,但是这时候是需要用appid的账户和密码进行登录,并不是用户;意思就是我们商家客户端拿到了用户的授权以后,用授权码换取token,这时候需要我们商家亮明身份换取token
  6. 实际中就是我们拿到用户授权码,以商家的身份换取用户token;注意需要post方法,认证方法选择basic,提供账号密码进行请求;就能获取到token
{
    "access_token": "9455a88a-f6c7-4916-bf51-4d5c054153c4",
    "token_type": "bearer",
    "expires_in": 43050,
    "scope": "all"
}
  1. oauth服务器拿到了token我们就可以去调用在我们这个中心注册了的商家的接口

小结:大致思路就是当
1.第三方软件请求联合登录的时候,会拉起主应用
2.主应用向服务器申请一个特殊的token[未登录提示登录],
3.然后token交给第三方应用
4.第三方应用拿着token就可以向主应用的服务器请求用户资源;[第三方应用未登录也要提示登录,也就是提供合作时我们分发的appid密钥]

资源服务保护的配置:
在我们需要保护资源的服务中创建一个资源服务配置类ResurceConifg继承ResourceServerConfigurerAdapter类;
注入两个参数,appid以及密钥;后续需要db查询
,配置了这个的服务在被请求时必须带上签发的正确token才行;

@Configuration//启用配置
@EnableResourceServer//启用资源服务
public class ResurceConifg extends ResourceServerConfigurerAdapter {

    private String appid = "employed";//这里后续需要从数据库中查询遍历用下面的方法填入内存
    private String appSecret = "employed_test_security";//这里后续需要从数据库中查询遍历用下面的方法填入内存

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Primary
    @Bean
    public RemoteTokenServices remoteTokenServices() {
        //这里后续需要从数据库中查询遍历用下面的方法填入内存
        final RemoteTokenServices tokenServices = new RemoteTokenServices();
        //设置授权服务器check_token的端点完整地址
        tokenServices.setCheckTokenEndpointUrl("http://127.0.0.1:18001/oauth/check_token");
        //设置客户端id与secret,这里的secret不能使用加密!
        tokenServices.setClientId(appid);
        tokenServices.setClientSecret(appSecret);
        return tokenServices;
    }


    @Override
    public void configure(HttpSecurity http) throws Exception {
        //设置创建session策略.设置请求后;
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
        //@formatter:off
        //设置所有请求都必须授权
        http.authorizeRequests()
                .anyRequest().authenticated();
        //@formatter:on

    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        //设置保护的资源,这个资源就是注册在我们oauth服务器内存中个各个商家的资源id,这个服务中要配置好这个才能保护; 
        resources.resourceId("employed_resource").stateless(true);
    }
}

http://127.0.0.1:18081/oauth/check_token?token=14d20998-864f-4eb7-9ca8-af1c86fbc1da

总结:

  1. 先向已登录用户索取同意操作,用户同意之后会以用户的身份颁布一个授权码;
  2. 第三方平台拿着授权码,向授权服务器申请token;
  3. 第三方平台使用accessToken就可以向授权服务器管辖的用户个人资源服务器请求数据,获取用户信息
  4. 第三方平台就可以根据用户信息进行登录或者注册操作;
  5. 补充:资源发布的时候会给自己指定一个资源id,而第三方进行accsesToken申请的时候也会指定一个资源id(数组),所以只能访问与之匹配的对应资源

误区:
之前一直以为是向授权服务器拿到token以后就可以用token访问第三方的资源了,正觉得奇怪,岂不是每次token都需要授权服务器来解密?
你要是头铁这么做也能用原来资源服务器并不是代表着第三方平台,而是代表着受开放平台管理用户资源

我开始还以为资源服务器就是第三方,第三方token经过授权服务器的验证后就可以请求第三方的接口;昨天测试的时候直接就把这个token放到业务代码里去了

感谢这个老哥的图解,一下就明白了,碰巧查资源id的时候看到的图
Spring Security OAuth2之resource_id配置与验证

想法:
由于一开始的不理解,所以也想了一些替代方法,这边记录一下,说不定会派上用场,第三方可以直接使用token进行替代用户登录,只是登录以后另外颁发一个用户的专属token然后就不用授权服务器的token了。。token失效以后再重新获取;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值