博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringBoot安全管理 ——模块3:OAuth 2的简单应用
阅读量:3947 次
发布时间:2019-05-24

本文共 8649 字,大约阅读时间需要 28 分钟。

OAuth 2的简单应用

首先我们了解下什么是 OAuth ,OAuth 是一个开放标准,此标准允许用户让第三方应用访问该用户在某一网站上存储的私密资源(例如头像,照片等),而在这个过程中无须将用户名和密码提供给第三方应用。实现这个功能是通过提供一个令牌 token ,而不是用户名和密码来访问他们存放在特定服务提供者的数据,每一个令牌授权一个特定的网站在特定的时间段内访问特定的资源

OAuth 2 授权流程图如下所示:

1.客户端 (第三方应用)向用户请求授权
2.用户单击客户端所呈现的服务授权页面上的同意按钮授权后,服务端返回一个授权许可证给客户端
3.客户端拿着授权许可证去授权服务器申请令牌
4.授权服务器验证信息无误后,发放令牌给客户端
5.客户端拿着令牌去资源服务器访问资源
6.资源服务器验证令牌无误后开放资源
在这里插入图片描述
1.创建项目,添加如下依赖:

org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-security
org.springframework.boot
spring-boot-starter-data-redis
io.lettuce
lettuce-core
redis.clients
jedis
org.springframework.security.oauth
spring-security-oauth2
2.3.3.RELEASE

接下来在 application.properties 中配置以下 Redis 服务器连接信息,代码如下:

spring.redis.database=0spring.redis.host=127.0.0.1spring.redis.port=6379spring.redis.password=123456spring.redis.jedis.pool.max-active=8spring.redis.jedis.pool.max-idle=8spring.redis.jedis.pool.max-wait=-1msspring.redis.jedis.pool.min-idle=0

配置完,需要启动Redis,我下载的是windows版本的Redis,首先你要下载 Redis

下载地址 https://www.runoob.com/redis/redis-install.html
然后下载后并解压,解压后的目录如下图所示:
在这里插入图片描述
然后在此目录下打开cmd命令行,输入此命令 redis-server.exe redis.windows.conf 就可以启动 redis 了,启动后如下图所示:
在这里插入图片描述
如果你的结果也是这样就代表本地 redis 启动成功了 ,成功后千万不要关闭这个窗口,因为你如果关闭了窗口 redis 也就关闭了,所以我们要启动它并使用它就不能关闭这个窗口
2.配置授权服务器
授权服务器和资源服务器可以是同一台机器,也可以是不同机器,这里我们模拟一下,假设是同一台服务器,通过不同的配置分别开启授权服务器和资源服务器,首先配置授权服务器,代码如下所示:

import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.security.authentication.AuthenticationManager;import org.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;import org.springframework.security.crypto.password.PasswordEncoder;import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;import javax.annotation.Resource;@Configuration@EnableAuthorizationServer //通过此注解开启授权服务器public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired //注入AuthenticationManager 用来支持 Password 模式 AuthenticationManager authenticationManager; @Autowired //注入RedisConnectionFactory 用来完成 Redis 缓存 RedisConnectionFactory redisConnectionFactory; @Autowired //注入UserDetailsService 此对象为刷新 token 提供支持 UserDetailsService userDetailsService; @Bean PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory() .withClient("password") .authorizedGrantTypes("password","refresh_token") //表示 OAuth 2中的授权模式为 password 和 refresh_token 两种 .accessTokenValiditySeconds(1800) //配置了 access_token 的过期时间 .resourceIds("rid") //配置了资源id .scopes("all") .secret("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq"); //配置了加密后的密码,明文是 123 } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(new RedisTokenStore(redisConnectionFactory)) .authenticationManager(authenticationManager) .userDetailsService(userDetailsService); //主要用于支持 Password 模式以及令牌的刷新 } @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients(); //表示支持 client_id 和 client_secret 作登陆认证 }}

3.配置资源服务器,代码如下:

import org.springframework.context.annotation.Configuration;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;@Configuration@EnableResourceServer	//通过此注解开启资源服务器public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("rid").stateless(true); } @Override public void configure(HttpSecurity http) throws Exception {
//配置 HttpSecuritys http.authorizeRequests() .antMatchers("/admin/**").hasRole("admin") .antMatchers("/user/**").hasRole("user") .anyRequest().authenticated(); }}

4.配置 Security ,代码如下:

import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.security.authentication.AuthenticationManager;import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;import org.springframework.security.core.userdetails.UserDetailsService;@Configurationpublic class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean(); } @Bean @Override protected UserDetailsService userDetailsService() {
return super.userDetailsService(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication() .withUser("admin").password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq").roles("admin") .and() .withUser("sang").password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq").roles("user"); } @Override protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/oauth/**").authorizeRequests() .antMatchers("/oauth/**").permitAll() .and().csrf().disable(); }}

5.测试验证

首先创建几个简单的请求地址,代码如下:

@RestControllerpublic class HelloController {
@GetMapping("/admin/hello") public String admin() {
return "hello admin!"; } @GetMapping("/user/hello") public String user() {
return "hello user!"; } @GetMapping("/hello") public String hello() {
return "hello"; }}

等待所有配置完成后,前面已经启动过 Redis 了,这里在启动 Spring Boot 项目,然后使用 Postman 进行测试,先发送一个 POST 请求获取 token ,请求地址如下: (注意这里是一个POST请求

http://localhost:8080/oauth/token?username=sang&password=123&grant_type=password&client_id=password&scope=all&client_secret=123
请求结果如下图所示:
在这里插入图片描述
access_token 是获取其他资源时要用的令牌
refresh_token 用来刷新令牌
expires_in 表示 access_token 的过期时间,当 access_token 过期后,使用 refresh_token 重新获取新的 access_token ,请求地址如下 (注意这里也是POST请求
http://localhost:8080/oauth/token?grant_type=refresh_token&refresh_token=39f3a87c-b286-4ea6-8e8e-2941b8f07b0c&client_id=password&client_secret=123
获取新的 access_token 时需要同时带上 refresh_token ,同时授权模式设置为 refresh_token ,在获取的结果中 access_token 会变化,同时 access_token 有效期也会变化 ,如下图所示:
在这里插入图片描述
接下来访问所有资源,带上 access_token 参数即可,例如 /user/hello 接口
http://localhost:8080/user/hello?access_token=fe612bb2-c849-4f2f-a12d-dd8a8ccb195f (注意这里是GET请求)
访问结果如下图:
在这里插入图片描述
如果非法访问一个资源,例如 sang 访问 /admin/hello 接口,结果如下
在这里插入图片描述
到这里,一个 password 模式的 OAuth 认证体系就搭建成功了。
欢迎评论,大家共同进步学习!

转载地址:http://piqwi.baihongyu.com/

你可能感兴趣的文章
两个行业的故事:编程语言与富裕国家和发展中国家之间的差异
查看>>
15个用于管理MySQL服务器mysqladmin命令
查看>>
服务器端I / O性能:Node,PHP,Java与Go
查看>>
多行文本编辑时,同一行编辑不同类型的字符时自动换行的问题
查看>>
如何使开机动画只播一次
查看>>
如何在平台上实现LED灯的效果?如信号灯,来短信/来电时LED动画闪烁
查看>>
restore factory属性的enable和disable
查看>>
Android LOG机制流程图
查看>>
如何在JNI中抛异常
查看>>
Android应用程序的完全退出
查看>>
Task和Activity相关的一些属性
查看>>
JAVA系统属性之user.home
查看>>
Android代码截屏
查看>>
Android中打印代码的调用层次
查看>>
成功者十三个价值连城的习惯
查看>>
特别成功的人会做6件事
查看>>
Android: 用jni 获取MAC地址
查看>>
字符串列表的C语言实现:c_strlist
查看>>
客户沟通的方式:礼貌待客沟通方式,技巧推广沟通方式,个性服务沟通方式
查看>>
用弹性工作制留住员工
查看>>