1、简介

  OAuth2共有5种模式,分别为:

  1. 授权码模式
  2. 隐藏模式
  3. 客户端模式
  4. 密码模式
  5. 刷新token模式

这里实现了比较简单的密码模式。

2、密码模式颁发access_token实现

2.1、maven工程结构如下:

image.png

添加pom依赖如下

<dependencies>  
 <!-- web -->
 <dependency> 
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-web</artifactId>  
 </dependency>  
 
 <!-- security -->  
 <dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-security</artifactId>  
 </dependency> 
  
  <!-- OAuth2 -->
 <dependency>                 
    <groupId>org.springframework.security.oauth.boot</groupId>  
    <artifactId>spring-security-oauth2-autoconfigure</artifactId>  
    <version>2.0.8.RELEASE</version>  
 </dependency>  
 
 <dependency> 
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-test</artifactId>  
    <scope>test</scope>  
    <exclusions> 
        <exclusion>   
            <groupId>org.junit.vintage</groupId>  
            <artifactId>junit-vintage-engine</artifactId>  
        </exclusion> 
    </exclusions> 
  </dependency>
 </dependencies>

2.2、配置文件application.properties内容如下:

server.port=9999  
spring.profiles.active=simple

2.3、认证服务器AuthorizationServer配置

@Profile("simple")  
@Configuration  
@EnableAuthorizationServer  //认证服务器注解
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {  
  
  @Autowired  
  private PasswordEncoder passwordEncoder;  
  
  @Autowired  
  private AuthenticationManager authenticationManager; //密码模式必须要注入authenticationManager,否则会报找不到authenticationManager错误
  
  @Override  
  public void configure(AuthorizationServerSecurityConfigurer security) throws Exception{  
        security.allowFormAuthenticationForClients();  
 super.configure(security);  //如果没有支持allowFormAuthenticationForClients或者有支持但是url中没有client_id和client_secret的,走basic认证保护。导致在浏览器中输入获取access_token时,会弹出窗口要求认证。
  }  
    @Override  
  public void configure(ClientDetailsServiceConfigurer clients) throws Exception{  
        clients.inMemory()  
            .withClient("client")  //客户端名称
                .secret(passwordEncoder.encode("client"))  //客户端密码
                .authorizedGrantTypes("password","refresh_token")  //密码模式
                .scopes("select")  //授权范围
                .resourceIds(ResourceServerConfig.RESOURCE_ID)  //资源服务器的id,这个在资源服务器里有配置。
                .accessTokenValiditySeconds(1200)  //有效时间
                .refreshTokenValiditySeconds(50000);  //refresh_token的有效时间
  }  
  
    @Override  
  public void configure(AuthorizationServerEndpointsConfigurer endpoints)throws Exception{  
        endpoints  
                .authenticationManager(authenticationManager);  //配置注入的authenticationManager
 super.configure(endpoints);  
  }  
  
  
  
}

2.4、资源服务器ResourceServer配置

@Profile("simple")  
@Configuration  
@EnableResourceServer  //资源服务器注解
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {  
  
    public static final String RESOURCE_ID = "authorizationserver";  //就是AuthorizationServerConfigurerAdapter中配置的那个,用来标识资源服务器
  
  @Override  
  public void configure(ResourceServerSecurityConfigurer resources) throws Exception{  
        super.configure(resources);  
  resources.resourceId(RESOURCE_ID);  //配置资源服务器的id
  }  
  
    @Override  
  public void configure(HttpSecurity http) throws Exception{  
        System.out.println("ResourceServerConfig中配置HttpSecurity对象执行");  
  http.requestMatchers().antMatchers("/me")  //配置"/me"是受保护的资源。要区分开springsecurity保护的端点和ResourceServer保护的端点。 
                .and()  
                .authorizeRequests()  
                .anyRequest().authenticated();  
  }  
  
}

2.5、配置WebSecurity

@Profile("simple")  
@Configuration  
@EnableWebSecurity(debug = true)  //可以不开启
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {  
  
  @Autowired  //注册用户,放到内存中
  public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception{  
        auth.inMemoryAuthentication()  
                .withUser("user").password(passwordEncoder().encode("user")).roles("USER")  
                .and()  
                .withUser("admin").password(passwordEncoder().encode("admin")).roles("ADMIN");  
  }  
  
  @Override  //配置不拦截"/oauth/**",否则在申请access_token会要求先认证
  protected void configure(HttpSecurity http) throws Exception{  
        System.out.println("SecurityConfiguration中配置的对象执行");  
  
  http  
                .requestMatchers().anyRequest()  
                .and()  
                .authorizeRequests()  
                .antMatchers("/oauth/**").permitAll();
  }  
  
    @Override  
  public void configure(WebSecurity web) throws Exception{  
        super.configure(web);  
  web.ignoring().antMatchers("favicon.ico");  
  }  
  
  
    @Bean  
  public PasswordEncoder passwordEncoder(){  
        return new BCryptPasswordEncoder();  
  }  
  
 @Bean //认证服务器中注入的authenticationManager就是从这里来的  
 @Override  public AuthenticationManager authenticationManager() throws Exception{  
        return super.authenticationManager();  
  }  
  
}

2.6、配置普通受springSecuity保护的端点

@Profile("simple")  
@RestController  
public class MainController {  
  
    @GetMapping("/")  
    public String email(){  
        return "这里是主页";  
  }  
  
    @GetMapping("/admin")  
    public String admin(){  
        return "这里是admin";  
  }  
  
    @GetMapping("/user")  
    public String user(){  
        return "这里是admin";  
  }  
}

2.7、配置受ResourceServer保护的端点

@Profile("simple")  
@RestController  
public class ResourceController {  
  
    @RequestMapping("/me")  
    public Principal me(Principal principal){  
        System.out.println(principal.toString());  
  
 return principal;  
  }  
  
}

2.8、main函数

@Profile("simple")  
@SpringBootApplication  
public class AuthSimpleApplication {  
  
    public static void main(String[] args) {  
        SpringApplication.run(AuthSimpleApplication.class, args);  
  }  
  
}

3、测试

3.1、测试获取access_token

在postman中输入以下链接:

http://localhost:9999/oauth/token?username=user&password=user&grant_type=password&scope=select&client_id=client&client_secret=client

返回以下内容:
image.png

3.2、测试获取资源服务器保护的内容:

image.png

3.3、测试普通端点

image.png

参考文章:

[阮一峰](http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html)  

SHIYIBODEC
26 声望2 粉丝

引用和评论

0 条评论