基于spring-boot-2.0.0
1,在pom.xml中添加:
<dependency> <groupId>org.springframework.security.oauthgroupId> <artifactId>spring-security-oauth2artifactId> <version>2.3.0.RELEASEversion> dependency> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-securityartifactId> dependency>
2,ServerConfig
package com.italkbb.homesecurity.alertmessage.security; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; 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; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; @Configuration @EnableAuthorizationServer //提供/oauth/authorize,/oauth/token,/oauth/check_token,/oauth/confirm_access,/oauth/error public class OAuth2ServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired PasswordEncoder bCryptPasswordEncoder;//定义在SecurityConfig 中@Bean public PasswordEncoder passwordEncoder() @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.tokenKeyAccess("permitAll()") .checkTokenAccess("isAuthenticated()") //allow check token .allowFormAuthenticationForClients(); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("app") .secret(bCryptPasswordEncoder.encode("app")) .authorizedGrantTypes("client_credentials", "password", "refresh_token") .scopes("all") .resourceIds("oauth2-resource") .and() .withClient("app1") .secret(bCryptPasswordEncoder.encode("app1")) .authorizedGrantTypes("client_credentials", "password", "refresh_token") .scopes("all") .resourceIds("oauth2-resource1") .accessTokenValiditySeconds(1200) .refreshTokenValiditySeconds(50000) ; } }
3,ResourceServerConfig
package com.italkbb.homesecurity.alertmessage.security; import org.springframework.context.annotation.Configuration; 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 { }
4,SecurityConfig
package com.italkbb.homesecurity.alertmessage.security; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 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.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.factory.PasswordEncoderFactories; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; /** * Created by wangyunfei on 2017/6/9. */ @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private DomainUserDetailsService userDetailsService; @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .anonymous().disable() .authorizeRequests() .antMatchers("/api-docs/**")//至少需要一个 .permitAll(); } @Bean public FilterRegistrationBean corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("*"); config.addAllowedHeader("*"); config.addAllowedMethod("*"); source.registerCorsConfiguration("/**", config); FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); bean.setOrder(0); return bean; } @Bean public DomainUserDetailsService userDetailsService(){ return new DomainUserDetailsService(); } @Bean public PasswordEncoder passwordEncoder() { System.out.println("============================passwordEncoder "); // return PasswordEncoderFactories.createDelegatingPasswordEncoder(); return new BCryptPasswordEncoder(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { System.out.println("============================configure "); auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder()); } //不定义没有password grant_type @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } class DomainUserDetailsService implements UserDetailsService { @Autowired PasswordEncoder bCryptPasswordEncoder; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { System.out.println("============================loadUserByUsername "+username); return new User("app",bCryptPasswordEncoder.encode("app"),null); } } }
现在随便访问你的controller mapping,都说无权限。需要先获取token:
$ curl -H "Accept: application/json" http://localhost/oauth/token -d "grant_type=client_credentials&client_id=app&client_secret=app"
然后再去访问:
http://localhost/api/order/11?access_token=32f044cd-48ef-4382-9a77-7ee35bd9a824
参考:
https://blog.csdn.net/wiselyman/article/details/84901713 用redis保存token。
https://github.com/bigben0123/uaa-zuul
https://atom.peg.ink/blog/2018/04/11/ji-yu-springbootde-api-keyshi-xian/ 自己实现
https://blog.csdn.net/yingziisme/article/details/82635190 报错问题
https://github.com/spring-projects/spring-security-oauth spring官方 oauth2
https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/test/resources/schema.sql 自己建立的用户存放库
https://github.com/spring-projects/spring-security-oauth/blob/master/docs/oauth2.md oauth2 developer guide
https://github.com/spring-projects/spring-security-oauth/tree/master/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider 源码,client目录下面有 jdbc和in-mem的实现。
https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java withClient, and等方法的实现
http://blog.didispace.com/spring-security-oauth2-xjf-1/ 程序员dd的最全介绍oauth
http://www.tianshouzhi.com/api/tutorials/spring_security_4/266 翻译官方的 spring security。不错!