在这里咱们使用Spring boot中的 secruity 和 Oauth2.0 搭建一个受权服务器 java
让其余应用或者服务使用用户名和密码 POST到这个服务器 来换取access_token spring
这种场景在实际应用中仍是很常见的api
具体方法请访问 https://my.oschina.net/u/659068/blog/1549186服务器
<!-- security --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> </dependency> <!-- security oauth2 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency>
这里主要就是设置了访问密码 路径配置等 其中 AuthenticationManager 是必须的app
@Configuration @EnableWebSecurity @Order(2) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private ClientDetailsService clientDetailsService; @Configuration protected static class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter { @Override public void init(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("user").password("zzz123") .roles("USER").and().withUser("admin").password("zzz123") .roles("USER", "ADMIN"); } } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("shili").password("zzz123").roles("ADMIN"); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .anonymous().disable() .authorizeRequests() .antMatchers("/oauth/token").permitAll() .and().exceptionHandling().authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/")); } @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Bean public TokenStore tokenStore() { return new InMemoryTokenStore(); } @Bean @Autowired public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore){ TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler(); handler.setTokenStore(tokenStore); handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService)); handler.setClientDetailsService(clientDetailsService); return handler; } @Bean @Autowired public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception { TokenApprovalStore store = new TokenApprovalStore(); store.setTokenStore(tokenStore); return store; } }
其中 allowFormAuthenticationForClients 是必须的 这里的 client_id 和 secret 也能够按照需求注册受权less
这里是写死的 这里之后会修改curl
@Configuration @EnableAuthorizationServer public class SecurityOauth2Config extends AuthorizationServerConfigurerAdapter { private static String REALM="MY_OAUTH_REALM"; @Autowired private TokenStore tokenStore; @Autowired private UserApprovalHandler userApprovalHandler; @Autowired @Qualifier("authenticationManagerBean") private AuthenticationManager authenticationManager; @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("13890999") .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") .scopes("read", "write", "trust") .secret("secret") .accessTokenValiditySeconds(120).//Access token is only valid for 2 minutes. refreshTokenValiditySeconds(600);//Refresh token is only valid for 10 minutes. } @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { //enable client to get the authenticated when using the /oauth/token to get a access token //there is a 401 authentication is required if it doesn't allow form authentication for clients when access /oauth/token oauthServer.allowFormAuthenticationForClients().realm(REALM+"/client"); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler) .authenticationManager(authenticationManager); } }
@Configuration @EnableResourceServer @Order(6) public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { private static final String RESOURCE_ID = "my_rest_api"; @Override public void configure(ResourceServerSecurityConfigurer resources) { resources.resourceId(RESOURCE_ID).stateless(false); } @Override public void configure(HttpSecurity http) throws Exception { http. anonymous().disable() .requestMatchers().antMatchers("/sayhello") .and().authorizeRequests() .antMatchers("/sayhello").access("hasRole('ADMIN')") .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()); } }
curl https://localhost:8080/oauth/token -k -d client_id=13890999 -d client_secret=secret -d grant_type=password -d username=shili -d password=zzz123
参数增长-k 跳过了证书的验证 不然就会出现错误提示 证书链是由不受信任的颁发机构颁发的。ide
看到以下信息 表示获取ACCESS_token 成功了! spring-boot
{"access_token":"66e5ab1d-427f-4801-a3c5-b47d3a96fbad","token_type":"bearer","re fresh_token":"cc9ef96f-d771-4ec9-a4fc-9064809886e3","expires_in":119,"scope":"re ad write trust"}