7、测试
获取授权码
附带上客户端id、回调url、获取请求的类型
输入账户密码
点击授权获取授权码
根据授权码获取令牌(POST请求)
grant_type
:授权类型,填写authorization_code,表示授权码模式code
:授权码,就是刚刚获取的授权码,注意:授权码只使用一次就无效了,需要重新申请。client_id
:客户端标识redirect_uri
:申请授权码时的跳转url,一定和申请授权码时用的redirect_uri一致。scope
:授权范围。
认证失败服务端返回 401 Unauthorized
注意:此时无法请求到令牌,访问服务器会报错
根据token去资源服务器拿资源
如果修改token就会报错
Spring Security Oauth2 密码模式
在上面的代码中进行适当的修改即可
SecurityConfig.java
package com.yjxxt.springsecurityoauth2demo.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; /** * Spring Security 配置类 * * @author ylc */ @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Override public void configure(HttpSecurity http) throws Exception { http.csrf() .disable() .authorizeRequests() .antMatchers("/oauth/**", "/login/**", "/logout/**") .permitAll() .anyRequest() .authenticated() .and() .formLogin() .permitAll(); } }
AuthorizationServerConfig.java
package com.yjxxt.springsecurityoauth2demo.config; import com.yjxxt.springsecurityoauth2demo.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; 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; /** * 授权服务器配置 * @author ylc * @since 1.0.0 */ @Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private PasswordEncoder passwordEncoder; @Autowired private AuthenticationManager authenticationManager; @Autowired private UserService userService; /** * 使用密码模式需要配置 */ @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) { endpoints.authenticationManager(authenticationManager) .userDetailsService(userService); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() //配置client_id .withClient("admin") //配置client-secret .secret(passwordEncoder.encode("112233")) //配置访问token的有效期 .accessTokenValiditySeconds(3600) //配置刷新token的有效期 .refreshTokenValiditySeconds(864000) //配置redirect_uri,用于授权成功后跳转 .redirectUris("http://www.baidu.com") //配置申请的权限范围 .scopes("all") //配置grant_type,表示授权类型 .authorizedGrantTypes("authorization_code","password"); } }
测试:
在Redis中存储token
之前的代码我们将token直接存在内存中,这在生产环境中是不合理的,下面我们将其改造成存储在Redis中
添加依赖及配置
pom.xml
<!--redis 依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- commons-pool2 对象池依赖 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency>
application.properties
# Redis配置 spring.redis.host=192.168.10.100
编写Redis配置类
RedisConfig.java
package com.yjxxt.springsecurityoauth2demo.config; 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.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore; /** * 使用redis存储token的配置 * @author ylc * @since 1.0.0 */ @Configuration public class RedisConfig { @Autowired private RedisConnectionFactory redisConnectionFactory; @Bean public TokenStore redisTokenStore(){ return new RedisTokenStore(redisConnectionFactory); } }
在认证服务器配置中指定令牌的存储策略为Redis
package com.yjxxt.springsecurityoauth2demo.config; import com.yjxxt.springsecurityoauth2demo.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; 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.provider.token.TokenStore; /** * 授权服务器配置 * @author ylc * @since 1.0.0 */ @Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private PasswordEncoder passwordEncoder; @Autowired private AuthenticationManager authenticationManager; @Autowired private UserService userService; @Autowired @Qualifier("redisTokenStore") private TokenStore tokenStore; /** * 使用密码模式需要配置 */ @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) { endpoints.authenticationManager(authenticationManager) .userDetailsService(userService) .tokenStore(tokenStore); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() //配置client_id .withClient("admin") //配置client-secret .secret(passwordEncoder.encode("112233")) //配置访问token的有效期 .accessTokenValiditySeconds(3600) //配置刷新token的有效期 .refreshTokenValiditySeconds(864000) //配置redirect_uri,用于授权成功后跳转 .redirectUris("http://www.baidu.com") //配置申请的权限范围 .scopes("all") //配置grant_type,表示授权类型 .authorizedGrantTypes("password"); } }
测试:
使用密码模式请求token