spring-security-oauth2 密码模式
OAuth 2
添加依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> <version>2.3.3.RELEASE</version> </dependency> <!--redis依赖配置--> <!--<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <exclusions> <exclusion> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency>
由于Spring Boot中的OAuth协议是在Spring Security的基础上完成的,因此首先要添加Spring Security依赖,
要用到OAuth 2,因此添加OAuth 2相关依赖,
令牌可以存储在Redis缓存服务器上,同时Redis具有过期等功能,很适合令牌的存储,因此也加入Redis依赖。
配置Redis服务器的连接信息:
spring:
redis:
host: localhost # Redis服务器地址
database: 0 # Redis数据库索引(默认为0)
port: 6379 # Redis服务器连接端口
password: # Redis服务器连接密码(默认为空)
jedis:
pool:
max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 8 # 连接池中的最大空闲连接
min-idle: 0 # 连接池中的最小空闲连接
timeout: 3000ms # 连接超时时间(毫秒)
配置授权服务器:
授权服务器和资源服务器可以是同一台服务器,也可以是不同服务器,本案例中假设是同一台服务器,通过不同的配置分别开启授权服务器和资源服务器,首先是授权服务器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | /** * 自定义类继承自AuthorizationServerConfigurerAdapter,完成对授权服务器的配置 */ @Configuration @EnableAuthorizationServer // 通过@EnableAuthorizationServer注解开启授权服务器 public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired AuthenticationManager authenticationManager; // 该对象将用来支持password模式 @Autowired RedisConnectionFactory redisConnectionFactory; // 该对象将用来完成Redis缓存,将令牌信息存储到Redis缓存中。 @Autowired UserDetailsService userDetailsService; // 该对象将为刷新token提供支持 @Bean PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient( "password" ) /* * 表示OAuth 2中的授权模式为“password”和“refresh_token”两种 * 在标准的OAuth 2协议中,授权模式并不包括“refresh_token”,但是在Spring Security的实现中将其归为一种, * 因此如果要实现access_token的刷新,就需要添加这样一种授权模式 */ .authorizedGrantTypes( "password" , "refresh_token" ) .accessTokenValiditySeconds( 1800 ) // 配置了access_token的过期时间 .resourceIds( "rid" ) // resourceIds配置了资源id .scopes( "all" ) .secret( "$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq" ); //secret方法配置了加密后的密码,明文是123 } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) { /* * 配置了令牌的存储,AuthenticationManager和UserDetailsService主要用于支持password模式以及令牌的刷新。 */ endpoints.tokenStore( new RedisTokenStore(redisConnectionFactory)) .authenticationManager(authenticationManager) .userDetailsService(userDetailsService); } @Override public void configure(AuthorizationServerSecurityConfigurer security) { security.allowFormAuthenticationForClients(); // 表示支持client_id和client_secret做登录认证 } } |
配置资源服务器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | @Configuration @EnableResourceServer // @EnableResourceServer注解开启资源服务器配置 public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(ResourceServerSecurityConfigurer resources) { // 配置资源id,这里的资源id和授权服务器中的资源id一致,然后设置这些资源仅基于令牌认证。 resources.resourceId( "rid" ).stateless( true ); } @Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers( "/admin/**" ).hasRole( "admin" ) .antMatchers( "/user/**" ).hasRole( "user" ) .anyRequest().authenticated(); } } |
配置Security:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | @Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { // 这里两个Bean将注入授权服务器配置类中使用 @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" ); } /** * 在Spring Security配置和资源服务器配置中,一共涉及两个HttpSecurity, * 其中Spring Security中的配置优先级高于资源服务器中的配置,即请求地址先经过Spring Security的HttpSecurity,再经过资源服务器的HttpSecurity。 */ @Override protected void configure(HttpSecurity http) throws Exception { http.antMatcher( "/oauth/**" ).authorizeRequests() .antMatchers( "/oauth/**" ).permitAll() //这里的HttpSecurity配置主要是配置“/oauth/**”模式的URL,这一类的请求直接放行 .and().csrf().disable(); } } |
测试验证:
启动Redis服务器,再启动Spring Boot项目,首先发送一个POST请求获取token,请求地址如下
POST http://127.0.0.1:8081/oauth/token?username=sang&password=123&grant_type=password&client_id=password&scope=all&client_secret=123
当access_token过期后,使用refresh_token重新获取新的access_token(前提是refresh_token未过期),请求地址如下
POST http://127.0.0.1:8081/oauth/token?grant_type=refresh_token&refresh_token=6b80de74-e264-4ca5-b 9cc-20e8a6fa486d&client_id=password&client_secret=123
接下来访问资源,携带上access_token参数即可
GET http://127.0.0.1:8081/user/hello?access_token=4c0ab1bd-5e01-4420-aa79-a4acf79fe7d2
文章来源: Spring Boot+Vue全栈开发实战 - 10.4 OAuth 2
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通