java 授权码模式_Oauth2认证模式之授权码模式实现

本文详细介绍了如何使用Java实现OAuth2的授权码模式。内容包括配置资源服务器、认证服务器和Spring Security,以及授权码模式的申请、访问令牌获取和使用。通过实例演示了授权流程,适合已了解Spring Security和OAuth2基础的读者。
摘要由CSDN通过智能技术生成

Oauth2认证模式之授权码模式(authorization code)

本示例实现了Oauth2之授权码模式,授权码模式(authorization code)是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与"服务提供商"的认证服务器进行互动。

阅读本示例之前,你需要先有以下两点基础:

需要对spring security有一定的配置使用经验,用户认证这一块,spring security oauth2建立在spring security的基础之上

oauth2开放授权标准基础,可以稳步到OAuth2 详解,浏览下授权码模式,理解下基本概念

概述

实现 oauth2,可以简易的分为三个步骤

配置资源服务器

配置认证服务器

配置spring security

代码实现

1.pom.xml添加maven依赖

org.springframework.security.oauth

spring-security-oauth2

2.3.6.RELEASE

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-thymeleaf

2.配置资源服务器

public class ResourceServerConfig {

private static final String RESOURCE_ID = "account";

@Configuration

@EnableResourceServer()

protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

@Override

public void configure(ResourceServerSecurityConfigurer resources) {

resources.resourceId(RESOURCE_ID).stateless(true);

}

@Override

public void configure(HttpSecurity httpSecurity) throws Exception {

httpSecurity

.requestMatchers()

// 保险起见,防止被主过滤器链路拦截

.antMatchers("/account/**").and()

.authorizeRequests().anyRequest().authenticated()

.and()

.authorizeRequests()

.antMatchers("/account/info/**").access("#oauth2.hasScope('get_user_info')")

.antMatchers("/account/child/**").access("#oauth2.hasScope('get_childlist')");

}

}

}

3.配置认证服务器

@Override

public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

clients.inMemory()

.withClient("client1")

.resourceIds(RESOURCE_ID)

.authorizedGrantTypes("authorization_code", "refresh_token", "implicit")

.authorities("ROLE_CLIENT")

.scopes("get_user_info", "get_childlist")

.secret("secret")

.redirectUris("http://localhost:8081/client/account/redirect")

.autoApprove(true)

.autoApprove("get_user_info");

}

4.配置spring security

@Configuration

@EnableWebSecurity

public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Bean

@Override

protected UserDetailsService userDetailsService() {

InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();

// 创建两个内存用户

manager.createUser(User.withUsername("admin").password("123456").authorities("USER").build());

manager.createUser(User.withUsername("lin").password("123456").authorities("USER").build());

return manager;

}

@Override

@Bean

public AuthenticationManager authenticationManagerBean() throws Exception {

return super.authenticationManagerBean();

}

@Bean

PasswordEncoder passwordEncoder(){

return NoOpPasswordEncoder.getInstance();

}

/**

* 密码生成器(默认为bcrypt模式)

*

* @return

*/

// @Bean

// PasswordEncoder passwordEncoder() {

// return PasswordEncoderFactories.createDelegatingPasswordEncoder();

// }

@Override

protected void configure(HttpSecurity httpSecurity) throws Exception {

httpSecurity.

requestMatchers()

// 必须登录过的用户才可以进行 oauth2 的授权码申请

.antMatchers("/", "/home", "/login", "/oauth/authorize")

.and()

.authorizeRequests()

.anyRequest().permitAll()

.and()

.formLogin()

.loginPage("/login")

.and()

.httpBasic()

.disable()

.exceptionHandling()

.accessDeniedPage("/login?authorization_error=true")

.and()

.csrf()

.requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize"))

.disable();

}

}

使用介绍

找到AuthResServerApplication.java运行server服务,默认端口:8080

找到ClientApplication.java运行client客户端,端口:8081

1.尝试直接访问用户信息

返回未授权错误

Full authentication is required to access this resource

unauthorized

2.尝试获取授权码

结果被主过滤器拦截,302 跳转到登录页,因为 /oauth/authorize 端点是受保护的端点,必须登录的用户才能申请 code。

3.输入用户名和密码

输入用户名和密码 admin 123456 如上用户名密码是交给 SpringSecurity 的主过滤器用来认证的

4.登录成功后,真正进行授权码的申请

oauth/authorize 认证成功,会根据 redirect_uri 执行 302 重定向,并且带上生成的 code,注意重定向到的是 8001 端口,这个时候已经是另外一个应用了。

localhost:8081/client/account/redirect?code=xxxx 代码中封装了一个 http 请求,使得 client1 使用 restTemplate 向 server 发送 token 的申请,当然是使用 code 来申请的,并最终成功获取到 access_token

{

access_token: "59a25558-f714-4ca8-aa87-c36f93c120bf",

token_type: "bearer",

refresh_token: "92436849-7ef7-4923-8270-5a2c9b464556",

expires_in: 43199,

scope: "get_user_info get_childlist"

}

5.携带 access_token 访问account信息

6.正常返回信息

{

name: "testAccount1",

nickName: "测试用户1",

remark: "备注1",

childAccount: [

{

name: "testChild1_0",

nickName: "测试子用户1_0",

remark: "0",

childAccount: null

},

{

name: "testChild1_1",

nickName: "测试子用户1_1",

remark: "1",

childAccount: null

},

{

name: "testChild1_2",

nickName: "测试子用户1_2",

remark: "2",

childAccount: null

},

{

name: "testChild1_3",

nickName: "测试子用户1_3",

remark: "3",

childAccount: null

},

{

name: "testChild1_4",

nickName: "测试子用户1_4",

remark: "4",

childAccount: null

},

{

name: "testChild1_5",

nickName: "测试子用户1_5",

remark: "5",

childAccount: null

},

{

name: "testChild1_6",

nickName: "测试子用户1_6",

remark: "6",

childAccount: null

},

{

name: "testChild1_7",

nickName: "测试子用户1_7",

remark: "7",

childAccount: null

},

{

name: "testChild1_8",

nickName: "测试子用户1_8",

remark: "8",

childAccount: null

},

{

name: "testChild1_9",

nickName: "测试子用户1_9",

remark: "9",

childAccount: null

}

]

}

资料

原文出处:https://www.cnblogs.com/tqlin/p/11341141.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值