赞
踩
当前应用需要实现第三方登入,那么第三方是如何进行授权认证的?这就是oauth2协议。
模拟实现微信端是如何进行授权认证登入。
举例:豆瓣就是客户应用,授权服务器、资源服务器就是微信端持有。豆瓣需要向微信的授权服务器获取授权,获取到授权后再向资源服务器获取用户信息。
那么我们就需要
1.需要配置一个授权服务器(发放授权码)
2.配置一个资源服务器(获取用户信息接口需要令牌才能访问)
3.配置一个接口(获取返回用户信息)
4.还要实现模拟用户的登入(因为授权服务器需要向用户发起是否允许授权的请求)
在spring-security-oauth2中有这几个默认接口,按照以下接口访问顺序获取用户信息:
/oauth/authorize:获取授权码 /oauth/token:根据授权码获取令牌 /user/getUser:根据令牌获取user资源信息
整个项目结构
项目依赖的pom文件:
注意:spring-cloud和spring-boot的版本一定要兼容适配,否则会报错
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- </dependency>
-
-
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-security</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-oauth2</artifactId>
- </dependency>
- </dependencies>
- <dependencyManagement>
- <dependencies>
- <!--springCloud的依赖-->
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-dependencies</artifactId>
- <version>Greenwich.SR2</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.context.annotation.Configuration;
- 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;
-
- /**
- * 授权服务器配置,客服端向此请求获取授权码
- *
- * 访问以下地址获取授权码:以下地址就是获取授权码的配置
- * http://localhost:8080/oauth/authorize?client_id=admin&response_type=code
- *
- * /oauth/authorize:获取授权码接口
- * response type=code:响应类型为授权码
- * client_d=admin:访问的授权服务器id
- */
- @Configuration
- @EnableAuthorizationServer
- public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
- @Autowired
- private PasswordEncoder passwordEncoder;
-
- @Override
- public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
- clients.inMemory()
- .withClient("admin") // 配置client-id
- .secret(passwordEncoder.encode("12334")) // 授权服务器的密码
- .accessTokenValiditySeconds(3600) // 时间有效期
- .redirectUris("http://www.baidu.com") // 授权成功后跳转地址(并且会带上授权码code)
- .scopes("all") // 授权范围
- .authorizedGrantTypes("authorization_code"); // 授权码模式
- }
- }
- 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;
-
- /**
- * 资源服务管理,配置某些接口需要携带令牌才能访问获取资源
- */
- @Configuration
- @EnableResourceServer
- public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
-
- @Override
- public void configure(HttpSecurity http) throws Exception {
- http.authorizeRequests()
- .anyRequest()
- .authenticated()
- .and()
- .requestMatchers()
- .antMatchers("/user/**");// 需要携带令牌才能访问获取资源
- }
- }
- @RestController
- @RequestMapping("/user")
- public class UserController {
-
- @RequestMapping("/getUser")
- public Object getUser(){
- return "成功获取到资源";// 给第三方网站返回用户信息(三方登入)
- }
- }
- @Service
- public class UserService implements UserDetailsService {
- @Autowired
- private PasswordEncoder passwordEncoder;
-
- @Override
- public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
- // 模拟根据username进行DB查询结果设置用户
- String password = passwordEncoder.encode("123");
- // 设置用户的账号、密码(security根据表单提交的登入信息进行比对)
- return new User("admin",password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
- }
- }
配置不需要登入认证才可访问的接口(如登入、退出登入接口)
- @Configuration
- @EnableWebSecurity
- public class SecurityConfig extends WebSecurityConfigurerAdapter {
- @Bean
- public PasswordEncoder passwordEncoder(){
- return new BCryptPasswordEncoder();
- }
-
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- http.csrf().disable()
- .authorizeRequests()
- .antMatchers("/login/**","/logout/**")
- .permitAll() // 以上接口允许不用授权服务
- .anyRequest()
- .authenticated() // 其它接口需要授权
- .and()
- .formLogin()
- .permitAll();
- }
- }
配置好以上信息后就可以开始进行测试了
第一步:访问http://localhost:8080/oauth/authorize?client_id=admin&response_type=code获取授权码code,首次获取时我们需要先登入用户(就好比如果手机微信不登入怎么进行授权)
登入成功后就会跳到这个页面(这个就是授权页面,就和微信询问你是否允许第三方应用登入一样)
选择允许授权后,跳到百度页面,并且携带了授权码code
接下来,我们就可以使用接口测试工具去获取令牌了(我使用的是Apifox)记得请求的端口要正确,下面截图中忘了写端口了。
发送请求后的返回体,access_token就是返回的令牌
接着携带令牌发送请求获取用户信息
请求结果
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。