很多人在進行專案開發時都會用到Oauth2.0結合SpringSecurity或者Shiro進行許可權攔截以及使用者驗證,網上也有很多的案例,前幾天專案裡邊需要用到,順便整合了進來,特此寫篇部落格,記錄下過程。
專案結構如下:
首先準備pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns=" xsi:schemaLocation=" <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.3.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <groupId>com.xz.springcloud</groupId> <artifactId>f-oauth2-pwd-mode</artifactId> <version>0.0.1-SNAPSHOT</version> <name>f-oauth2-pwd-mode</name> <description>Demo project for Spring Boot</description> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Finchley.RELEASE</spring-cloud.version> <oauth.version>2.3.3.RELEASE</oauth.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> <version>2.2.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
MyUserDetailService.java
package com.oauth.config;import java.util.ArrayList;import java.util.List;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.authority.SimpleGrantedAuthority;import org.springframework.security.core.userdetails.User;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.core.userdetails.UsernameNotFoundException;import org.springframework.stereotype.Component;/** * * @author yuxuan * */@Componentpublic class MyUserDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // TODO 這個地方可以透過username從資料庫獲取正確的使用者資訊,包括密碼和許可權等。 List<GrantedAuthority> grantedAuthorityList = new ArrayList<>(); grantedAuthorityList.add(new SimpleGrantedAuthority("ROLE_USER")); grantedAuthorityList.add(new SimpleGrantedAuthority("ROLE_ADMIN")); return new User(username, "{noop}123456", grantedAuthorityList); } }
OAuth2ServerConfig.java
package com.oauth.config;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Configuration;import org.springframework.http.HttpMethod;import org.springframework.security.authentication.AuthenticationManager;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;import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;@Configuration@EnableAuthorizationServerpublic class OAuth2ServerConfig extends AuthorizationServerConfigurerAdapter { @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer .tokenKeyAccess("permitAll()") //url:/oauth/token_key,exposes public key for token verification if using JWT tokens .checkTokenAccess("isAuthenticated()") //url:/oauth/check_token allow check token .allowFormAuthenticationForClients(); } /** * 注入authenticationManager * 來支援 password grant type */ @Autowired private AuthenticationManager authenticationManager; @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager); endpoints.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("client") .secret("{noop}secret") .authorizedGrantTypes("client_credentials", "password", "refresh_token") .scopes("all") .resourceIds("resourcesId") .accessTokenValiditySeconds(1200) .refreshTokenValiditySeconds(50000); } }
ResourceServerConfig.java
package com.oauth.config;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;import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;@Configuration@EnableResourceServerpublic class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.requestMatchers().antMatchers("/api/**").and().authorizeRequests().antMatchers("/api/**").authenticated(); } @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { resources.resourceId("resourcesId").stateless(true); } }
WebConfig.java
package com.oauth.config;import org.springframework.context.annotation.Bean;import org.springframework.security.authentication.AuthenticationManager;import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;@EnableWebSecurity@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)public class WebConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); http.requestMatchers().antMatchers("/oauth/**") .and() .authorizeRequests() .antMatchers("/oauth/**").authenticated(); } /** * 需要配置這個支援password模式 support password grant type * @return * @throws Exception */ @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } }
IndexCtrl.java
package com.oauth.ctrl;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class IndexCtrl { @GetMapping("hello") public String hello() { return "Hello World"; } @GetMapping("api/hello") public String apiHello() { return "Hello World"; } }
App.java
package com.oauth;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
以上就是一個程式碼的配置,下面啟動App類,執行main函式。專案啟動完成後用rest client訪問hello介面
可以看到提示無效的token,接下我們請求獲取token。利用CURL命令請求如下:
curl -i -X POST -d "username=admin&password=123456&grant_type=password&client_id=client&client_secret=secret"
可以看到,至此已經訪問成功了。
也可以利用GET方式直接訪問,如下:
有問題可以在下面評論,技術問題可以私聊我。