不熟悉的先看下前面的security 登录 原理是一样的
这里我把JDBC 和 Redis都加上了
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency>
数据库相关 主要是一个mysql 驱动 和 druid连接池
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.9</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
reids 缓存
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
另外看个人需求 Eureka注册或者网关之类的 我的POM

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>tsearch_web</groupId> <artifactId>etest-aouth</artifactId> <version>0.0.1</version> <packaging>jar</packaging> <name>etest-aouth</name> <description>Note Server catch</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.M3</spring-cloud.version> </properties> <dependencies> <!-- oauth2相关 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> <!-- jdbc --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.9</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.RELEASE</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> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> </project>
application.yml
spring: redis: host: 127.0.0.1 password: 123654 datasource: url: jdbc:mysql://localhost:3306/oauth2?useUnicode=true&characterEncoding=utf-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&useSSL=false username: root password: root type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver server: port: 9002
mysql 的数据表根据github上的建就行
https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/test/resources/schema.sql
Druid连接池配置
import com.alibaba.druid.pool.DruidDataSource; @Configuration public class DruidConfig { @Value("${spring.datasource.url}") private String dbUrl; @Value("${spring.datasource.type}") private String type; @Value("${spring.datasource.username}") private String username; @Value("${spring.datasource.password}") private String password; @Value("${spring.datasource.driver-class-name}") private String driverClassName; @Bean public DataSource druidDataSource() { DruidDataSource datasource = new DruidDataSource(); datasource.setUrl(dbUrl); datasource.setUsername(username); datasource.setPassword(password); datasource.setDriverClassName(driverClassName); return datasource; } }
SecurityConfiguration 配置
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired private UserDetailService userDetailService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // TODO Auto-generated method stub auth.userDetailsService(userDetailService); } @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().antMatchers("/","/hello","/login2","/oauth/token").permitAll() .anyRequest() .fullyAuthenticated() .and() .formLogin() .loginPage("/login2").permitAll() .failureForwardUrl("/error") .loginProcessingUrl("/login") .successForwardUrl("/hello") .and().logout() .permitAll() .and() .csrf().disable();; // System.out.println(http.toString()); } @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/css/**", "/js/**", "/plugins/**", "/favicon.ico"); } }
我们先看下出存储Token的方式 是集成TokenStore
spring 给我们个提供了以下几种选择方式
看字面意思很容易理解 InMemory 内存 Jdbc数据库 Redis,JWT的话不进行存储 直接放在令牌里 如果不主动设置的话 他会默认选取
private TokenStore tokenStore() { if (tokenStore == null) { if (accessTokenConverter() instanceof JwtAccessTokenConverter) { this.tokenStore = new JwtTokenStore((JwtAccessTokenConverter) accessTokenConverter()); } else { this.tokenStore = new InMemoryTokenStore(); } } return this.tokenStore; }
AuthorizationServerConfiguration
@Configuration @EnableAuthorizationServer public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { @Autowired AuthenticationManager authenticationManager; @Autowired RedisConnectionFactory redisConnectionFactory; @Autowired private DataSource dataSource; @Autowired private UserDetailService userDetailService; @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { //clients.withClientDetails(clientDetails());
clients.jdbc(dataSource).withClient("dikeboy")
.resourceIds(Utils.RESOURCEIDS.ORDER)
.authorizedGrantTypes("client_credentials", "password,refresh_token")
.scopes("server")
.authorities("oauth2")
.secret(passwordEncoder().encode("123456"));
//一开始往数据库里插入一条client 后面有了可以注释掉换成上面的直接从数据库取 } @Bean public ClientDetailsService clientDetails() { return new JdbcClientDetailsService(dataSource); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.tokenStore(redisTokenStore()) .userDetailsService(userDetailService) .authenticationManager(authenticationManager) .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST); endpoints.tokenServices(defaultTokenServices()); } @Primary @Bean public DefaultTokenServices defaultTokenServices(){ DefaultTokenServices tokenServices = new DefaultTokenServices(); tokenServices.setTokenStore(redisTokenStore()); tokenServices.setSupportRefreshToken(true); tokenServices.setClientDetailsService(clientDetails()); tokenServices.setAccessTokenValiditySeconds(60*60*12); // token有效期自定义设置,默认12小时 tokenServices.setRefreshTokenValiditySeconds(60 * 60 * 24 * 7);//默认30天,这里修改 return tokenServices; } @Bean MyRedisTokenStore redisTokenStore(){ return new MyRedisTokenStore(redisConnectionFactory); } @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security.allowFormAuthenticationForClients().tokenKeyAccess("permitAll()") .checkTokenAccess("isAuthenticated()"); } @Bean PasswordEncoder passwordEncoder() { return PasswordEncoderFactories.createDelegatingPasswordEncoder(); } }
UserDetailService
@Service(value = "userDetailService") public class UserDetailService implements UserDetailsService { @Autowired private PasswordEncoder passwordEncode; public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { System.out.println("username=" + username); List<GrantedAuthority> list = new ArrayList<GrantedAuthority>(); list.add(new SimpleGrantedAuthority("ROLE_USER")); User auth_user = new User("dikeboy", passwordEncode.encode("123456"), list); return auth_user; } @Bean PasswordEncoder passwordEncoder() { return PasswordEncoderFactories.createDelegatingPasswordEncoder(); } }