Spring Security Oauth2 示例
所有示例的依赖如下(均是SpringBoot项目)
pom.xml
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><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></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-jwt</artifactId></dependency></dependencies>
一、ResourceServer(资源服务器)
application.yml
server: port: 8082 context-path: /resourceserver
启动类
@SpringBootApplicationpublic class ResourceServerApplication {public static void main(String[] args) {SpringApplication.run(ResourceServerApplication.class, args);}}
TestController.java(暴露RESTful接口)
@RestControllerpublic class TestController {@GetMapping("/product/{id}")public String product(@PathVariable String id) {retu "product id : " + id;}@GetMapping("/order/{id}")public String order(@PathVariable String id) {retu "order id : " + id;}@GetMapping("/pomer/{id}")public String pomer(@PathVariable String id) {retu "pomer id : " + id;}}
配置类 ResourceServerConfig(配置JWT形式的token)
@EnableResourceServer@Configurationpublic class ResourceServerConfig {@Beanpublic TokenStore tokenStore() {retu new JwtTokenStore(jwtAccessTokenConverter());}@Beanpublic JwtAccessTokenConverter jwtAccessTokenConverter() {JwtAccessTokenConverter converter = new JwtAccessTokenConverter();converter.setSigningKey("123");retu converter;}}
配置类 MyResourceServerConfigurer(配置访问权限)
@Configurationpublic class MyResourceServerConfigurer extends ResourceServerConfigurerAdapter {@Overridepublic void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/product/**").permitAll().antMatchers("/order/**").authenticated().antMatchers("/pomer/**").access("#oauth2.hasScope('read_profile') and hasAuthority('ADMIN')");}}
二、AuthorizationServer 授权服务器(授权码模式,authorization code)
application.yml
server: port: 8081 context-path: /authorizationserver
启动类
@SpringBootApplicationpublic class AuthorizationServerApplication {public static void main(String[] args) {SpringApplication.run(AuthorizationServerApplication.class, args);}}
配置类 AuthorizationServerConfig(配置JWT形式的token)
@EnableAuthorizationServer@Configurationpublic class AuthorizationServerConfig {@Beanpublic TokenStore tokenStore() {retu new JwtTokenStore(jwtAccessTokenConverter());}@Beanpublic JwtAccessTokenConverter jwtAccessTokenConverter() {JwtAccessTokenConverter converter = new JwtAccessTokenConverter();converter.setSigningKey("123");retu converter;}}
配置类 MyAuthorizationServerConfigurer
@Configurationpublic class MyAuthorizationServerConfigurer extends AuthorizationServerConfigurerAdapter {@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate TokenStore tokenStore;@Autowiredprivate JwtAccessTokenConverter jwtAccessTokenConverter;@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.tokenStore(tokenStore).accessTokenConverter(jwtAccessTokenConverter).authenticationManager(authenticationManager);}@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient("clientApp").secret("123456").redirectUris("http://localhost:9000/callback").authorizedGrantTypes("authorization_code").scopes("read_profile", "read_contacts");}}
配置类 MyWebSecurityConfigurerAdapter(配置用户名密码)
@Configurationpublic class MyWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser("user").password("123456").authorities("USER").and().withUser("admin").password("123456").authorities("USER", "ADMIN");}}
开始测试!打开浏览器访问:
http://localhost:8081/authorizationserver/oauth/authorize?client_id=clientApp&redirect_uri=http://localhost:9000/callback&response_type=code&scope=read_profile
显示登录页面,输入用户名密码,返回重定向302(授权码位于参数部分)
http://localhost:9000/callback?code=EWfpi5
根据授权码,请求令牌:
> curl -X POST --user clientApp:123456 http://localhost:8081/authorizationserver/oauth/token -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=authorization_code&redirect_uri=http://localhost:9000/callback&scope=read_profile&code=EWfpi5"# clientApp:123456 经Base64编码得 'Y2xpZW50QXBwOjEyMzQ1Ng=='POST /authorizationserver/oauth/token HTTP/1.1Host: localhost:8081Content-Type: application/x-www-form-urlencodedAuthorization: Basic Y2xpZW50QXBwOjEyMzQ1Ng==Cache-Control: no-cachePostman-Token: c6c182c7-5df1-46ea-9cb7-130ff250c93ccode=F4QesT&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A9000%2Fcallback&scope=read_profile
得到令牌:
{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NDE4NTExMTYsInVzZXJfbmFtZSI6InVzZXIiLCJhdXRob3JpdGllcyI6WyJVU0VSIl0sImp0aSI6ImMyYzQ4YTc0LWI4MjUtNGNlYS05NGU3LTMyM2VlN2Q4NTk2ZCIsImNsaWVudF9pZCI6ImNsaWVudEFwcCIsInNjb3BlIjpbInJlYWRfcHJvZmlsZSJdfQ.Oc1TN7fMPgNVXX7k8dEw0QqosD7ZKQ198c-Qa2l1Gho","token_type":"bearer","expires_in":43199,"scope":"read_profile","jti":"c2c48a74-b825-4cea-94e7-323ee7d8596d"}
根据令牌请求资源
> curl http://localhost:8082/resourceserver/order/12 -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NDE4NTExMTYsInVzZXJfbmFtZSI6InVzZXIiLCJhdXRob3JpdGllcyI6WyJVU0VSIl0sImp0aSI6ImMyYzQ4YTc0LWI4MjUtNGNlYS05NGU3LTMyM2VlN2Q4NTk2ZCIsImNsaWVudF9pZCI6ImNsaWVudEFwcCIsInNjb3BlIjpbInJlYWRfcHJvZmlsZSJdfQ.Oc1TN7fMPgNVXX7k8dEw0QqosD7ZKQ198c-Qa2l1Gho"GET /resourceserver/order/12 HTTP/1.1Host: localhost:8082Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NDE4NTExMTYsInVzZXJfbmFtZSI6InVzZXIiLCJhdXRob3JpdGllcyI6WyJVU0VSIl0sImp0aSI6ImMyYzQ4YTc0LWI4MjUtNGNlYS05NGU3LTMyM2VlN2Q4NTk2ZCIsImNsaWVudF9pZCI6ImNsaWVudEFwcCIsInNjb3BlIjpbInJlYWRfcHJvZmlsZSJdfQ.Oc1TN7fMPgNVXX7k8dEw0QqosD7ZKQ198c-Qa2l1GhoCache-Control: no-cachePostman-Token: 913a8844-1308-47d8-afa3-a9f288323c20
返回资源
order id : 12
附:/product/* 允许任何人访问,/order/* 需要用户认证,而 /pomer/* 只允许拥有ADMIN权限的admin用户访问,测试有效
三、AuthorizationServer 授权服务器(简化模式,implicit)
只修改配置类 MyAuthorizationServerConfigurer,其余代码不变
@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient("clientApp").secret("123456").redirectUris("http://localhost:9000/callback").authorizedGrantTypes("implicit").scopes("read_profile","read_contacts");}
开始测试!打开浏览器访问:
http://localhost:8081/authorizationserver/oauth/authorize?client_id=clientApp&redirect_uri=http://localhost:9000/callback&response_type=token&scope=read_profile&state=xyz
显示登录页面,输入用户名密码,返回重定向302(令牌位于hash部分):
http://localhost:9000/callback#access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NDE4NjMxNjMsInVzZXJfbmFtZSI6InVzZXIiLCJhdXRob3JpdGllcyI6WyJVU0VSIl0sImp0aSI6ImQ2MzYxYzZjLTIyZWYtNDU2ZC1iOGJhLWY4ZTE5MzMwMTBmOSIsImNsaWVudF9pZCI6ImNsaWVudEFwcCIsInNjb3BlIjpbInJlYWRfcHJvZmlsZSJdfQ.BRwtzF2rFc6w8WECqYETZbkCSDdoOzKdF4Zm_SAZuao&token_type=bearer&state=xyz&expires_in=119&jti=d6361c6c-22ef-456d-b8ba-f8e1933010f9
得到令牌,后续请求资源相同,不再重复叙述
四、AuthorizationServer 授权服务器(密码模式,resource owner password credentials)
修改配置类 MyAuthorizationServerConfigurer
@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient("clientApp").secret("123456").authorizedGrantTypes("password").scopes("read_profile", "read_contacts");}
在默认情况下 AuthorizationServerEndpointsConfigurer 配置没有开启密码模式,只有配置了 authenticationManager 才会开启密码模式,如下
在 MyWebSecurityConfigurerAdapter.java 新增一段代码(配置 authenticationManager Bean)
@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {retu super.authenticationManagerBean();}
在 MyAuthorizationServerConfigurer.java 新增一段代码(令 AuthorizationServerEndpointsConfigurer 设置 authenticationManager)
@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate TokenStore tokenStore;@Autowiredprivate JwtAccessTokenConverter jwtAccessTokenConverter;@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) {endpoints.tokenStore(tokenStore).accessTokenConverter(jwtAccessTokenConverter).authenticationManager(authenticationManager);}
开始测试!请求令牌
> curl -X POST --user clientApp:123456 http://localhost:8081/authorizationserver/oauth/token -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=password&scope=read_profile&useame=user&password=123456"
得到令牌:
{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NDE5MDk4MTcsInVzZXJfbmFtZSI6InVzZXIiLCJhdXRob3JpdGllcyI6WyJVU0VSIl0sImp0aSI6ImJhZDk1OTI0LTdkYTgtNDUyMy05YzZkLTBkNzY3NTlmYjQ1NiIsImNsaWVudF9pZCI6ImNsaWVudEFwcCIsInNjb3BlIjpbInJlYWRfcHJvZmlsZSJdfQ.gO5_kl8_OBRnj2Dt5glflXAIJrbyioYXezV-ZQ8BxL4","token_type":"bearer","expires_in":43199,"scope":"read_profile","jti":"bad95924-7da8-4523-9c6d-0d76759fb456"}
得到令牌,后续请求资源相同,不再重复叙述
五、AuthorizationServer 授权服务器(客户端模式,client credentials)
只修改配置类 MyAuthorizationServerConfigurer,其余代码不变
@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient("clientApp").secret("123456").authorizedGrantTypes("client_credentials").scopes("read_profile", "read_contacts");}
开始测试!请求令牌
> curl -X POST --user clientApp:123456 http://localhost:8081/authorizationserver/oauth/token -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials&scope=read_profile"
得到令牌:
{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6WyJyZWFkX3Byb2ZpbGUiXSwiZXhwIjoxNTQxOTEwOTEzLCJqdGkiOiI5MDVjNzc2OS1lNGQ2LTQxYTItYjcyMC1jYzliZWZjYzE5MDQiLCJjbGllbnRfaWQiOiJjbGllbnRBcHAifQ.c6UiHxbCdioCklkCqkLsCG6C8KHwwzajlPka6ut5MJs","token_type":"bearer","expires_in":43199,"scope":"read_profile","jti":"905c7769-e4d6-41a2-b720-cc9befcc1904"}
得到令牌,后续请求资源相同,不再重复叙述
作者:不完全個体
来源链接:https://www.cnblogs.com/pomer-huang/p/pomer_huang.html
版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。
2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。