目录
2.1.2、JwsswUserDetailsService类
2.1.3、AuthorizationServerConfig类
4.1、https://www.cnblogs.com/fengzheng/p/11724625.html
4.2、http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
4.3、https://blog.csdn.net/WYA1993/article/details/85050120
4.4、https://www.jianshu.com/p/c987c208859d
4.5、https://blog.csdn.net/MongolianWolf/article/details/94329980
1、环境
jdk11
netbean11.2
spring boot 2.2.1.RELEASE
spring cloud Hoxton.RELEASE
2、代码
2.1、认证服务
创建一个my-auth工程,按照下面搭建这个认证服务。
2.1.1、AuthApplication类
package com.jwssw.auth;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author Rewloc
* @version 1.0
* @date 2020/1/16 14:01
* @since JDK 11
*/
@Slf4j
@SpringBootApplication
public class AuthApplication {
public static void main(String[] args) {
log.info("认证服务器启动");
SpringApplication.run(AuthApplication.class, args);
log.info("认证服务器启动结束");
}
}
2.1.2、JwsswUserDetailsService类
package com.jwssw.auth.server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* @author Rewloc
* @version 1.0
* @date 2020/1/16 14:10
* @since JDK 11
*/
@Slf4j
@Component
public class JwsswUserDetailsService implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
log.info("usernameis:" + username);
// 查询数据库操作
if (!"admin".equals(username)) {
throw new UsernameNotFoundException("the user is not found");
} else {
// 用户角色也应在数据库中获取
String role = "ROLE_ADMIN";
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority(role));
authorities.add(new SimpleGrantedAuthority("sys:user:view"));
// 线上环境应该通过用户名查询数据库获取加密后的密码
String password = passwordEncoder.encode("123456");
return new org.springframework.security.core.userdetails.User(username, password, authorities);
}
}
}
2.1.3、AuthorizationServerConfig类
package com.jwssw.auth.config;
import com.jwssw.auth.server.JwsswUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
/**
* @author Rewloc
* @version 1.0
* @date 2020/1/16 14:12
* @since JDK 11
*/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
public PasswordEncoder passwordEncoder;
@Autowired
public JwsswUserDetailsService userDetailsService;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private TokenStore redisTokenStore;
@Override
public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
/**
* redis token 方式
*/
endpoints.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService)
.tokenStore(redisTokenStore);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("order-client")
.secret(passwordEncoder.encode("order-secret-8888"))
.authorizedGrantTypes("refresh_token", "authorization_code", "password")
// .accessTokenValiditySeconds(3600)
.accessTokenValiditySeconds(120)
.scopes("all")
.and()
.withClient("user-client")
.secret(passwordEncoder.encode("user-secret-8888"))
.authorizedGrantTypes("refresh_token", "authorization_code", "password")
// .accessTokenValiditySeconds(3600)
.accessTokenValiditySeconds(120)
.scopes("all");
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients();
security.checkTokenAccess("isAuthenticated()");
security.tokenKeyAccess("isAuthenticated()");
}
}
2.1.4、RedisTokenStoreConfig类
package com.jwssw.auth.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
/**
* @author Rewloc
* @version 1.0
* @date 2020/1/16 14:16
* @since JDK 11
*/
@Configuration
public class RedisTokenStoreConfig {
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Bean
public TokenStore redisTokenStore() {
return new RedisTokenStore(redisConnectionFactory);
}
}
2.1.5、WebSecurityConfig类
package com.jwssw.auth.config;
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.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* @author Rewloc
* @version 1.0
* @date 2020/1/16 14:07
* @since JDK 11
*/
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 密码加密方式
*
* @return 密码加密对象
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
* 允许匿名访问所有接口 主要是 oauth 接口
*
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").permitAll();
}
}
2.1.6、application.yml
server:
port: 8001
spring:
application:
name: auth-server
redis:
database: 2
host: 127.0.0.1
port: 6379
password:
jedis:
pool:
max-active: 8
max-idle: 8
min-idle: 0
timeout: 100ms
2.1.6、pom.xml
<?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>
<groupId>com.jwssw</groupId>
<artifactId>my-auth</artifactId>
<version>1.0.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>11</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</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-actuator</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.2、业务服务
创建一个my-user工程,按照下面搭建这个认证服务。
2.2.1、UserApplication类
package com.jwssw.user;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author Rewloc
* @version 1.0
* @date 2020/1/16 14:35
* @since JDK 11
*/
@SpringBootApplication
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
2.2.2、ResourceServerConfig类
package com.jwssw.user.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
/**
* @author Rewloc
* @version 1.0
* @date 2020/1/16 14:35
* @since JDK 11
*/
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Value("${security.oauth2.client.client-id}")
private String clientId;
@Value("${security.oauth2.client.client-secret}")
private String secret;
@Value("${security.oauth2.authorization.check-token-access}")
private String checkTokenEndpointUrl;
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Bean
public TokenStore redisTokenStore() {
return new RedisTokenStore(redisConnectionFactory);
}
@Bean
public RemoteTokenServices tokenService() {
RemoteTokenServices tokenService = new RemoteTokenServices();
tokenService.setClientId(clientId);
tokenService.setClientSecret(secret);
tokenService.setCheckTokenEndpointUrl(checkTokenEndpointUrl);
return tokenService;
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.tokenServices(tokenService());
}
}
2.2.3、UserController类
package com.jwssw.user.web;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author Rewloc
* @version 1.0
* @date 2020/1/16 15:07
* @since JDK 11
*/
@Slf4j
@RestController
public class UserController {
@GetMapping(value = "get")
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
// @PreAuthorize("hasAnyRole('ROLE_ADMIN_GET')")
public Object get(Authentication authentication) {
log.info("我真的进来了!!!");
//Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
authentication.getCredentials();
OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails();
String token = details.getTokenValue();
return token;
}
@PostMapping("hello")
@PreAuthorize("hasAuthority('sys:user:view')")
public String hello(){
return "hello";
}
}
2.2.4、application.yml
server:
port: 8101
spring:
application:
name: user-server
redis:
database: 2
host: 127.0.0.1
port: 6379
password:
jedis:
pool:
max-active: 8
max-idle: 8
min-idle: 0
timeout: 100ms
# 这是重点!!!
security:
oauth2:
client:
client-id: user-client
client-secret: user-secret-8888
user-authorization-uri: http://localhost:8001/oauth/authorize
access-token-uri: http://localhost:8001/oauth/token
resource:
id: user-client
user-info-uri: user-info
authorization:
check-token-access: http://localhost:8001/oauth/check_token
2.2.5、pom.xml
<?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>
<groupId>com.jwssw</groupId>
<artifactId>my-user</artifactId>
<version>1.0.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>11</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
3、测试
按照上面搭建完认证服务和业务服务之后,就可以进行测试了。本次测试使用了Postman工具完成。
3.1、获取access_token
POST http://localhost:8001/oauth/token?grant_type=password&username=admin&password=123456&scope=all
最后一步就可以点击【Send】获取access_token值了,结果如上图所示。
3.2、认证测试
获取access_token值后,就可以调用业务RUI了。将access_token值放入到②中文本框。
最后,点击【Send】按钮就可以返回结果。
4、参考
4.1、https://www.cnblogs.com/fengzheng/p/11724625.html
4.2、http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
4.3、https://blog.csdn.net/WYA1993/article/details/85050120
4.4、https://www.jianshu.com/p/c987c208859d
4.5、https://blog.csdn.net/MongolianWolf/article/details/94329980