oauth2授权码登录源码php,OAuth2-授权码模式 登录流程

一.案例架构

主要包括如下服务:

1.第三方应用

2.授权服务器

3.资源服务器

4.用户

项目端口备注

auth-server

8080

授权服务器

user-server

8081

资源服务器

client-app

8082

第三方应用

首先来创建一个空的 Maven 父工程,创建好之后,里边什么都不用加,也不用写代码。我们将在这个父工程中搭建这个子模块

二.授权服务器搭建

首先我们搭建一个名为 auth-server 的授权服务,搭建的时候,选择如下三个依赖:

1.web

2.spring cloud security

3.spirng cloud OAuth2

创建完成之后提供一个SpringSecurity的基本配置

在这里配置的,就是用户的用户名/密码/角色信息。

@Configurationpublic class SecurityConfig extendsWebSecurityConfigurerAdapter {

@Bean

PasswordEncoder passwordEncoder() {return newBCryptPasswordEncoder();

}

@Overrideprotected void configure(AuthenticationManagerBuilder auth) throwsException {

auth.inMemoryAuthentication()

.withUser("test1")

.password(new BCryptPasswordEncoder().encode("123456"))

.roles("admin")

.and()

.withUser("test2")

.password(new BCryptPasswordEncoder().encode("123456"))

.roles("user");

}

@Overrideprotected void configure(HttpSecurity http) throwsException {

http.csrf().disable().formLogin();

}

}

配置授权服务器

@Configurationpublic classAccessTokenConfig {

//生成的 Token 要往哪里存储 可以存在 Redis 中,也可以存在内存中,也可以结合 JWT 等等

@Bean

TokenStore tokenStore() {return newInMemoryTokenStore(); //它存在内存中

}

}

// 这个类继承AuthorizationServerConfigureAdapter 对授权服务器的详细配置

@EnableAuthorizationServer //表示开启授权服务器的自动化配置。

@Configurationpublic class AuthorizationServer extendsAuthorizationServerConfigurerAdapter {

@Autowired

TokenStore tokenStore;

@Autowired

ClientDetailsService clientDetailsService;

//主要用来配置 Token 的一些基本信息

@Bean

AuthorizationServerTokenServices tokenServices() {

DefaultTokenServices services= newDefaultTokenServices();

services.setClientDetailsService(clientDetailsService);

services.setSupportRefreshToken(true); //是否支持刷新

services.setTokenStore(tokenStore); //token 存储的位置

services.setAccessTokenValiditySeconds(60 * 60 * 2); //token的有效期

services.setRefreshTokenValiditySeconds(60 * 60 * 24 * 3); // 刷新token的有效期returnservices;

}

//用来配置令牌端点的安全约束,也就是这个端点谁能访问,谁不能访问

@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throwsException {

security.checkTokenAccess("permitAll()") //checkTokenAccess 是指一个 Token 校验的端点

.allowFormAuthenticationForClients(); //设置为可以直接访问 当资源服务器收到 Token 之后,需要去校验Token 的合法性,就会访问这个端点

}

//配置客户端的详细信息

@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throwsException {

clients.inMemory() //存储到内存中

.withClient("test") //客户端的id

.secret(new BCryptPasswordEncoder().encode("123"))

.resourceIds("rid") //资源id

.authorizedGrantTypes("authorization_code","refresh_token") //授权类型

.scopes("all") //资源范围

.redirectUris("http://localhost:8082/index.html"); //重定向url

}

//配置令牌的访问端点和令牌服务

@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throwsException {

endpoints.authorizationCodeServices(authorizationCodeServices()) //authorizationCodeService用来配置授权码的存储 这里我们是存在在内存中

.tokenServices(tokenServices()); //配置令牌的存储 即 access_token 的存储位置

}

@Bean

AuthorizationCodeServices authorizationCodeServices() {return newInMemoryAuthorizationCodeServices();

}

}

授权码和令牌有什么区别?授权码是用来获取令牌的,使用一次就失效,令牌则是用来获取资源的

三.资源服务器搭建

资源服务器就是用来存放用户的资源,例如你在微信上的图像、openid 等信息,用户从授权服务器上拿到 access_token 之后,接下来就可以通过 access_token 来资源服务器请求数据。

我们创建一个新的 Spring Boot 项目,叫做 user-server ,作为我们的资源服务器,创建时,添加如下依赖:

1.web

2.spring cloud security

3.spirng cloud OAuth2

配置资源服务器  (如果是小项目,资源和授权服务器可以放一起,大项目就要分开)

@Configuration

@EnableResourceServerpublic class ResourceServerConfig extendsResourceServerConfigurerAdapter {

//配置了一个 RemoteTokenServices 的实例 这是因为资源服务器和授权服务器是分开的,如果放一起就不需要配置 RemoteTokeService

@Bean

RemoteTokenServices tokenServices() {

RemoteTokenServices services= newRemoteTokenServices();

services.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token"); //access_token 的校验地址

services.setClientId("test"); //client_id

services.setClientSecret("123"); //client_secretreturnservices;

}

//资源拦截规则

@Overridepublic void configure(ResourceServerSecurityConfigurer resources) throwsException {

resources.resourceId("res1").tokenServices(tokenServices());

}

//请求规则

@Overridepublic void configure(HttpSecurity http) throwsException {

http.authorizeRequests()

.antMatchers("/admin/**").hasRole("admin")

.anyRequest().authenticated();

}

}

测试接口

@RestControllerpublic classHelloController {

@GetMapping("/hello")publicString hello() {return "hello";

}

@GetMapping("/admin/hello")publicString admin() {return "admin";

}

}

四.第三方应用搭建

一个普通的 Spring Boot 工程,创建时加入 Thymeleaf 依赖和 Web 依赖:

在 resources/templates 目录下,创建 index.html ,内容如下:

Oauth2 第三方登录

@Controllerpublic classHelloController {

@Autowired

RestTemplate restTemplate;

@GetMapping("/index.html")publicString hello(String code, Model model) {if (code != null) {

MultiValueMap map = new LinkedMultiValueMap<>();

map.add("code", code);

map.add("client_id", "test");

map.add("client_secret", "123");

map.add("redirect_uri", "http://localhost:8082/index.html");

map.add("grant_type", "authorization_code");

Map resp = restTemplate.postForObject("http://localhost:8080/oauth/token", map, Map.class);

String access_token= resp.get("access_token");

System.out.println(access_token);

HttpHeaders headers= newHttpHeaders();

headers.add("Authorization", "Bearer " +access_token);

HttpEntity httpEntity = new HttpEntity<>(headers);

ResponseEntity entity = restTemplate.exchange("http://localhost:8081/admin/hello", HttpMethod.GET, httpEntity, String.class);

model.addAttribute("msg", entity.getBody());

}return "index";

}

}

如果 code 不为 null,也就是如果是通过授权服务器重定向到这个地址来的,那么我们做如下两个操作:

根据拿到的 code,去请求 http://localhost:8080/oauth/token 地址去获取 Token,返回的数据结构如下:

{"access_token": "e7f223c4-7543-43c0-b5a6-5011743b5af4", //请求数据所需要的令牌"token_type": "bearer","refresh_token": "aafc167b-a112-456e-bbd8-58cb56d915dd", //刷新token所需要的令牌"expires_in": 7199, //token有效期还剩多久"scope": "all"}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值