java oauth2 例子_使用SpringSecurityOAuth2配置自定义Token实现OAuth2授权示例

本文记录一下使用SpringSecurityOAuth2配置自定义Token实现OAuth2授权的步骤

1、相关知识

2、构建项目

本文使用的springboot版本是2.0.4.RELEASE,不同版本可能会有所区别。下面是主要的配置文件和类:

1)pom依赖

org.springframework.boot

spring-boot-starter-security

org.springframework.security.oauth.boot

spring-security-oauth2-autoconfigure

2.1.3.RELEASE

2)application.properties

#不需要,暂时写死在代码中,重构时移植到此处即可

3)主配置类

@EnableWebSecurity

@Configurationpublic class WebSecurityConfig extendsWebSecurityConfigurerAdapter{

@Overrideprotected void configure(HttpSecurity http) throwsException {

http.httpBasic().and().csrf().disable();

}

@Bean("authenticationManager")public AuthenticationManager authenticationManagerBean() throwsException {return super.authenticationManagerBean();

}

@BeanpublicPasswordEncoder passwordEncoder() {return newBCryptPasswordEncoder();

}

}

4)用户认证类

@Component

public class MyUserDetailsService implementsUserDetailsService{

@AutowiredprivatePasswordEncoder passwordEncoder;

@Overridepublic UserDetails loadUserByUsername(String username) throwsUsernameNotFoundException {

System.out.println("登录用户名:"+username);

String password= passwordEncoder.encode("123456");return new User(username,password,true,true,true,true,

AuthorityUtils.commaSeparatedStringToAuthorityList("admin,ROLE_USER"));

}

}

5)认证服务类

@Configuration

@EnableAuthorizationServerpublic class AuthorizationServerConfig extendsAuthorizationServerConfigurerAdapter{

@AutowiredprivateAuthenticationManager authenticationManager;

@AutowiredprivateUserDetailsService userDetailsService;

@AutowiredprivatePasswordEncoder passwordEncoder;

@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throwsException {

endpoints

.authenticationManager(authenticationManager)

.userDetailsService(userDetailsService);

}

@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throwsException {

clients

.inMemory()//Token保存在内存中

.withClient("MyProject").secret(passwordEncoder.encode("MyProject_123"))//指明client-id和client-secret

.accessTokenValiditySeconds(7200)//令牌有效时间,单位秒

.authorizedGrantTypes("refresh_token","password","authorization_code")//支持刷新令牌、密码模式、授权码模式

.scopes("all","read","write")//权限有哪些,如果这两配置了该参数,客户端发请求可以不带参数,使用配置的参数

.redirectUris("http://127.0.0.1:8080/login");

}

}

说明:

a)client-secret必须加密,否则在后面测试中,总是弹出让输入用户名、密码。

b)代码中配置了权限,客户端可以不携带scopes参数,如果携带必须是all、read、write或者其组合。

c)使用授权码模式,必须配置redirectUris,使用密码模式可以不配置,去掉该语句即可。

6)启动类

@SpringBootApplicationpublic classApp {public static voidmain(String[] args) {

SpringApplication.run(App.class, args);

}

}

3、测试验证

1)验证默认scope情况获取Token

3540f315a93051c0672c56f339b40e4c.png

e24c55af03a2b5d40c79fcf4bf374e9d.png

2)验证指定scope情况获取Token

84fcc96d173260e1798cad592c59596d.png

说明:

a)发送参数是all write,返回scope是all write

b)发送参数是write read,返回scope是read write

c)发送除了all read write以外的任何scope值,都返回"Invalid scope",不能用逗号分隔。

3)验证授权码模式

00584b870c731ed5352bdd8653752d7b.png

b)输入用户名任意,密码123456

29e930b0302655b9d950c94430733533.png

c)点击Authorize,浏览器跳转如下地址,授权码为GPLd04

fb85973cc6a81c0fedf340bd022d6bdf.png

d)获取Token

1b1af13dc60c141ef69f0f3588a6913b.png

ba05966ac10159295b8a4fefcaf3681d.png

4、给多个应用发送Token

修改认证服务类中configure方法,如下,模拟给两个应用发送令牌:

@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throwsException {

InMemoryClientDetailsServiceBuilder builder=clients.inMemory();

List list = new ArrayList();

String app1= "MyProject,MyProject_123,7200";

String app2= "Test,Test123,10";

list.add(app1);

list.add(app2);

String client= "";

String secret= "";intaccessTokenValiditySeconds;for(String str:list) {

client= str.split(",")[0];

secret= str.split(",")[1];

accessTokenValiditySeconds= Integer.valueOf(str.split(",")[2]);

builder.withClient(client).secret(passwordEncoder.encode(secret))

.accessTokenValiditySeconds(accessTokenValiditySeconds)

.refreshTokenValiditySeconds(2592000)

.authorizedGrantTypes("refresh_token","password")

.scopes("all","read","write");

}

}

5、使用Redis存储Token

使用Redis存储Token,当应用重启后,Token不会改变。

1)引入Redis依赖,并添加配置

org.springframework.boot

spring-boot-starter-data-redis

spring.redis.host = 192.168.7.151spring.redis.port= 637

2)配置TokenStore为Redis

@Configurationpublic classTokenStoreConfig {

@AutowiredprivateRedisConnectionFactory redisConnectionFactory;

@BeanpublicTokenStore redisTokenStore() {return newRedisTokenStore(redisConnectionFactory);

}

}

3)修改认证服务类中configure方法,给endpoints指定Token存储方式为Redis

@AutowiredprivateTokenStore tokenStore;

@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throwsException {

endpoints

.tokenStore(tokenStore)

.authenticationManager(authenticationManager)

.userDetailsService(userDetailsService);

}

4)演示,初始时候Redis的key为空,当Rest插件请求一次Token后,Redis中写入了数据。重启应用再访问,Token不改变。

bf40d18de412f71dee01e2a67945c08f.png


版权声明:本文为weixin_35252964原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。