SpringSecurity+OAuth2+密碼模式

一、簡介

  OAuth2共有5種模式,分別爲:html

  1. 受權碼模式
  2. 隱藏模式
  3. 客戶端模式
  4. 密碼模式
  5. 刷新token模式

這裏實現了比較簡單的密碼模式。web

二、密碼模式頒發access_token實現

2.一、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.二、配置文件application.properties內容以下:

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

2.三、認證服務器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.四、資源服務器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.五、配置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.六、配置普通受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.七、配置受ResourceServer保護的端點

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

2.八、main函數

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

三、測試

3.一、測試獲取access_token

在postman中輸入如下連接:spring

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

返回如下內容:
image.png瀏覽器

3.二、測試獲取資源服務器保護的內容:

image.png

3.三、測試普通端點

image.png

參考文章:

[阮一峯](http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html)
相關文章
相關標籤/搜索