码云: https://gitee.com/alanfans/sping-cloud-oauth.git
build:
compile('org.springframework.cloud:spring-cloud-starter-oauth2')
compile('org.springframework.cloud:spring-cloud-starter-security')
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile group: 'com.alibaba', name: 'druid', version: '1.1.9'
runtime('mysql:mysql-connector-java')
runtime('org.springframework.boot:spring-boot-devtools')
compileOnly('org.projectlombok:lombok')
testCompile('org.springframework.boot:spring-boot-starter-test')
springBootVersion = '2.0.2.RELEASE'
jdk:1.8
gradle:2.0
OAuth2Configuration:
package com.sce.core.security;
import java.util.concurrent.TimeUnit;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
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.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import com.sce.core.service.UserService;
public class OAuth2Configuration {
@Configuration
@EnableResourceServer
private class ResourceServerConfiguration extends ResourceServerConfigurerAdapter{
@Autowired
private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
@Autowired
private CustomLogouSuccessHandler customLogouSuccessHandler;
@Override
public void configure(HttpSecurity http) throws Exception{
http
.exceptionHandling()
.authenticationEntryPoint((AuthenticationEntryPoint) customAuthenticationEntryPoint)
.and()
.logout()
.logoutUrl("/oauth/logout")
.logoutSuccessHandler((LogoutSuccessHandler) customLogouSuccessHandler)
.and()
.authorizeRequests()
.antMatchers("/hello/").permitAll()
.antMatchers("/secure").authenticated();
}
}
@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
// private static final String ENV_OAUTH = "security.oauth2.client.";
// private static final String PROP_CLIENT = ENV_OAUTH + "client-id";
// private static final String PROP_SECRET= ENV_OAUTH + "client-secret";
// private static final String PROP_TOKEN_VALIDITY_SECONDS = ENV_OAUTH + "access-token-validity-seconds";
//
// @Autowired
// private Environment environmnent;
@Autowired
private DataSource dataSource;
@Autowired
private UserService userService;
// @Autowired
// private ClientDetailsService clientDetailsService;
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Bean // 声明 ClientDetails实现
public ClientDetailsService clientDetails() {
return new JdbcClientDetailsService(dataSource);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.tokenStore(tokenStore())
.authenticationManager(authenticationManager)
.userDetailsService(userService);
// 配置TokenServices参数
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setTokenStore(endpoints.getTokenStore());
tokenServices.setSupportRefreshToken(false);
tokenServices.setClientDetailsService(endpoints.getClientDetailsService());
tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
tokenServices.setAccessTokenValiditySeconds( (int) TimeUnit.DAYS.toSeconds(30)); // 30天
endpoints.tokenServices(tokenServices);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(dataSource);
// .withClient(environmnent.getProperty(PROP_CLIENT))
// .scopes("read", "wirte")
// .authorities(Authorities.ROLE_ADMIN.name(), Authorities.ROLE_USER.name())
// .authorizedGrantTypes("client_credentials", "password", "refresh_token")
// .secret(environmnent.getProperty(PROP_SECRET))
// .accessTokenValiditySeconds(environmnent.getProperty(PROP_TOKEN_VALIDITY_SECONDS, Integer.class, 1800));1800
}
}
}
SecurityConfiguration:
package com.sce.core.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler;
import com.sce.core.service.UserService;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
@Autowired
private UserService userService;
//配置匹配用户时密码规则
public PasswordEncoder passwordEncoder() {
//自适应所有密码规则
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
//配置全局设置
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
//设置UserDetailsService以及密码规则
auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
}
//排除/hello路径拦截
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/hello");
/*web.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();*/
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
//开户全局方法拦截
@EnableGlobalMethodSecurity(prePostEnabled = true,jsr250Enabled = true)
public static class GlobalSecurityConfiguration extends GlobalMethodSecurityConfiguration {
protected MethodSecurityExpressionHandler createExpressionHandler() {
return new OAuth2MethodSecurityExpressionHandler();
}
}
public static void main(String[] args) {
System.out.println(PasswordEncoderFactories.createDelegatingPasswordEncoder().encode("admin"));
}
}
UserService:
package com.sce.core.service;
import java.util.ArrayList;
import java.util.Collection;
import org.springframework.beans.factory.annotation.Autowired;
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;
import com.sce.core.entity.AuthorityEntity;
import com.sce.core.entity.UserEntity;
import com.sce.core.jpa.UserJPA;
@Component("UserService")
public class UserService implements UserDetailsService {
@Autowired
private UserJPA userJPA;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserEntity userEntity = userJPA.findByUserEntityNameCaseInsensitive(username.toLowerCase());
if(null == userEntity) {
throw new UsernameNotFoundException("user "+username+" was not found int the database");
}
//获取用户的所有权限并且SpringSecurity需要的集合
Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();
for(AuthorityEntity authority : userEntity.getAuthorities()) {
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(authority.getRoleName());
grantedAuthorities.add(grantedAuthority);
}
//返回一个SpringSecurity需要的用户对象
return new User(userEntity.getUsername(),userEntity.getPassword(),grantedAuthorities);
}
}