related
-
Spring Cloud Series 1 – Service Registration and Discovery Eureka
-
Spring Cloud – Client calls Rest + Ribbon
-
Spring Cloud Combat Series iii – Declarative client Feign
-
Spring Cloud Series iv – Fuse Hystrix
-
Spring Cloud Combat Series 5 – Service Gateway Zuul
-
Spring Cloud Deployment Series (6) – Distributed Configuration center Spring Cloud Config
-
Spring Cloud Combat Series (7) – Service Link Tracking Spring Cloud Sleuth
-
Spring Cloud Combat Series (8) – Micro service monitoring Spring Boot Admin
-
Spring Cloud OAuth 2.0
-
Single sign-on JWT and Spring Security OAuth
preface
OAuth 2.0 is an intermediate layer between user resources and third-party applications. It separates resources from third-party applications so that third-party applications cannot directly access resources, thus protecting resources. In order to access this restricted resource, third-party applications (clients) need to provide credentials at the time of access.
The body of the
1. Introduction to OAuth 2.0
During authentication and authorization, the following roles are involved:
-
Service provider: Authorization Server
-
Resource owner: Resource Server
-
Client: Client
The authentication process of OAuth 2.0 is shown as follows:
-
The user (resource holder) opens the client, which asks the user for authorization.
-
The user agrees to authorize.
-
The client applies for authorization from the authorization server.
-
The authorization server authenticates the client, including user information, and authorizes the token after successful authentication.
-
After the client obtains the token, it requests resources from the resource server with the token.
-
The resource server verifies that the token is correct and issues resources to the client.
OAuth2 Provider roles are divided into Authorization Server (Authorization Service) and Resource Service (Resource Service), usually not in the same Service. One Authorization Service may correspond to multiple Resource Services. Spring OAuth2.0 is used in conjunction with Spring Security. All requests are handled by the Spring MVC controller and intercepted by a series of Spring Security filters.
There are two endpoints in the Spring Security filter chain that are used to obtain authentication and Authorization from the Authorization Service.
-
Endpoints for authorization: default to /oauth/authorize.
-
Endpoint used to get the token: default is /oauth/token.
2. Create a local database
Client information can be stored in a database so that data for client information can be updated in real time by changing the database. Spring OAuth2 has designed the tables of the database and is immutable. Start by importing the following DDL into the database.
SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for `clientdetails`
-- ----------------------------
DROP TABLE IF EXISTS `clientdetails`;
CREATE TABLE `clientdetails` (
`appId` varchar(128) NOT NULL.`resourceIds` varchar(256) DEFAULT NULL.`appSecret` varchar(256) DEFAULT NULL.`scope` varchar(256) DEFAULT NULL.`grantTypes` varchar(256) DEFAULT NULL.`redirectUrl` varchar(256) DEFAULT NULL.`authorities` varchar(256) DEFAULT NULL.`access_token_validity` int(11) DEFAULT NULL.`refresh_token_validity` int(11) DEFAULT NULL.`additionalInformation` varchar(4096) DEFAULT NULL.`autoApproveScopes` varchar(256) DEFAULT NULL,
PRIMARY KEY (`appId`))ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for `oauth_access_token`
-- ----------------------------
DROP TABLE IF EXISTS `oauth_access_token`;
CREATE TABLE `oauth_access_token` (
`token_id` varchar(256) DEFAULT NULL.`token` blob.`authentication_id` varchar(128) NOT NULL.`user_name` varchar(256) DEFAULT NULL.`client_id` varchar(256) DEFAULT NULL.`authentication` blob.`refresh_token` varchar(256) DEFAULT NULL,
PRIMARY KEY (`authentication_id`))ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for `oauth_approvals`
-- ----------------------------
DROP TABLE IF EXISTS `oauth_approvals`;
CREATE TABLE `oauth_approvals` (
`userId` varchar(256) DEFAULT NULL.`clientId` varchar(256) DEFAULT NULL.`scope` varchar(256) DEFAULT NULL.`status` varchar(10) DEFAULT NULL.`expiresAt` datetime DEFAULT NULL.`lastModifiedAt` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for `oauth_client_details`
-- ----------------------------
DROP TABLE IF EXISTS `oauth_client_details`;
CREATE TABLE `oauth_client_details` (
`client_id` varchar(256) NOT NULL.`resource_ids` varchar(256) DEFAULT NULL.`client_secret` varchar(256) DEFAULT NULL.`scope` varchar(256) DEFAULT NULL.`authorized_grant_types` varchar(256) DEFAULT NULL.`web_server_redirect_uri` varchar(256) DEFAULT NULL.`authorities` varchar(256) DEFAULT NULL.`access_token_validity` int(11) DEFAULT NULL.`refresh_token_validity` int(11) DEFAULT NULL.`additional_information` varchar(4096) DEFAULT NULL.`autoapprove` varchar(256) DEFAULT NULL,
PRIMARY KEY (`client_id`))ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for `oauth_client_token`
-- ----------------------------
DROP TABLE IF EXISTS `oauth_client_token`;
CREATE TABLE `oauth_client_token` (
`token_id` varchar(256) DEFAULT NULL.`token` blob.`authentication_id` varchar(128) NOT NULL.`user_name` varchar(256) DEFAULT NULL.`client_id` varchar(256) DEFAULT NULL,
PRIMARY KEY (`authentication_id`))ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for `oauth_code`
-- ----------------------------
DROP TABLE IF EXISTS `oauth_code`;
CREATE TABLE `oauth_code` (
`code` varchar(256) DEFAULT NULL.`authentication` blob
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for `oauth_refresh_token`
-- ----------------------------
DROP TABLE IF EXISTS `oauth_refresh_token`;
CREATE TABLE `oauth_refresh_token` (
`token_id` varchar(256) DEFAULT NULL.`token` blob.`authentication` blob
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for `role`
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`))ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for `user`
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`password` varchar(255) DEFAULT NULL.`username` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UK_sb8bbouer5wak8vyiiy4pf2bx` (`username`))ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for `user_role`
-- ----------------------------
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role` (
`user_id` bigint(20) NOT NULL.`role_id` bigint(20) NOT NULL.KEY `FKa68196081fvovjhkek5m97n3y` (`role_id`),
KEY `FK859n2jvi8ivhui0rl0esws6o` (`user_id`),
CONSTRAINT `FK859n2jvi8ivhui0rl0esws6o` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
CONSTRAINT `FKa68196081fvovjhkek5m97n3y` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`))ENGINE=InnoDB DEFAULT CHARSET=utf8;
SET FOREIGN_KEY_CHECKS = 1;
Copy the code
3. Create a Maven project
Using Maven’s multi-module project structure, create an empty Maven project and configure the Spring Boot version 1.5.3.RELEASE in the pom. XML file in the root directory. The Spring Cloud version is dalston.release and the complete code is as follows:
<?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>1.5.3. RELEASE</version>
<relativePath/>
</parent>
<modules>
<module>eureka-server</module>
<module>service-auth</module>
<module>service-hi</module>
</modules>
<groupId>io.github.ostenant.springcloud</groupId>
<artifactId>spring-cloud-oauth2-example</artifactId>
<version>0.0.1 - the SNAPSHOT</version>
<name>spring-cloud-oauth2-example</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Dalston.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</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>
</project>
Copy the code
4. Create Eureka Server
4.1. Create an application module
Create a new Eureka-server module, add eureka dependencies, and specify the parent node of pom.xml as follows:
<?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>io.github.ostenant.springcloud</groupId>
<artifactId>eureka-server</artifactId>
<version>0.0.1 - the SNAPSHOT</version>
<packaging>jar</packaging>
<name>eureka-server</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>io.github.ostenant.springcloud</groupId>
<artifactId>spring-cloud-oauth2-example</artifactId>
<version>0.0.1 - the SNAPSHOT</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Copy the code
4.2. The configuration application. Yml
Configure the eureka server information in the application. Yml configuration file of the Eureka server module:
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
Copy the code
4.3. Configure the application startup class
Finally, add @enableEurekaserver annotation to the application startup class to enable the EurekaServer function.
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); }}Copy the code
5. Create the Uaa authorization service
5.1. Create an Application module
Create a new service-auth module and add the following dependencies as Uaa (authorization service). The complete code is as follows:
<?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>io.github.ostenant.springcloud</groupId>
<artifactId>service-auth</artifactId>
<version>0.0.1 - the SNAPSHOT</version>
<packaging>jar</packaging>
<name>service-auth</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>io.github.ostenant.springcloud</groupId>
<artifactId>spring-cloud-oauth2-example</artifactId>
<version>0.0.1 - the SNAPSHOT</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Copy the code
When you open the spring-Cloud-starter-OAuth2 dependency package, you can see that it already integrates the following three starter dependencies:
-
spring-cloud-starter-security
-
spring-security-oauth2
-
spring-security-jwt
5.2. The configuration application. Yml
Application. Yml in the service-oauth module completes the following configuration:
spring:
application:
name: service-auth
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/spring-cloud-auth? useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
username: root
password: 123456
jpa:
hibernate:
ddl-auto: update
show-sql: true
server:
context-path: /uaa
port: 5000
security:
oauth2:
resource:
filter-order: 3
# basic:
# enabled: false
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
Copy the code
Configure security. Oauth2. Resource. The filter – the order for 3, in the Spring the Boot 1.5 x version before, can omit this configuration.
5.3. Configure security authentication
Auth-service is also a resource service. Spring Security needs to be introduced into auth-Service and relevant configurations need to be completed. In this way, auth-service resources are protected.
WebSecurityConfig.java
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserServiceDetail userServiceDetail;
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http.authorizeRequests().anyRequest().authenticated()
.and()
.csrf().disable();
// @formatter:on
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userServiceDetail).passwordEncoder(new BCryptPasswordEncoder());
}
@Override
public @Bean AuthenticationManager authenticationManagerBean(a) throws Exception {
return super.authenticationManagerBean(); }}Copy the code
UserServiceDetail.java
@Service
public class UserServiceDetail implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
returnuserRepository.findByUsername(username); }}Copy the code
To configure the relational mapping class User for the table, implement the UserDetails interface:
@Entity
public class User implements UserDetails.Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true)
private String username;
@Column
private String password;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
private List<Role> authorities;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
// setter getter
@Override
public boolean isAccountNonExpired(a) {
return true;
}
@Override
public boolean isAccountNonLocked(a) {
return true;
}
@Override
public boolean isCredentialsNonExpired(a) {
return true;
}
@Override
public boolean isEnabled(a) {
return true; }}Copy the code
GrantedAuthority = GrantedAuthority = GrantedAuthority = GrantedAuthority
@Entity
public class Role implements GrantedAuthority {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
// setter getter
@Override
public String getAuthority(a) {
return name;
}
@Override
public String toString(a) {
returnname; }}Copy the code
UserRepository.java
public interface UserRepository extends JpaRepository<User.Long> {
User findByUsername(String username);
}
Copy the code
5.4. Configure the Authentication Server
Configure the authentication Server, using the @ EnableAuthorizationServer annotations open Authorization Server, provides the function of authentication and Authorization.
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
// Store the Token in memory
// private TokenStore tokenStore = new InMemoryTokenStore();
private TokenStore tokenStore = new JdbcTokenStore(dataSource);
@Autowired
@Qualifier("dataSource")
private DataSource dataSource;
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Autowired
private UserServiceDetail userServiceDetail;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// Store the client information in memory
clients.inMemory()
// create a client named browser
.withClient("browser")
// Configure the authentication type
.authorizedGrantTypes("refresh_token"."password")
// Set the client domain to "UI"
.scopes("ui")
.and()
.withClient("service-hi")
.secret("123456")
.authorizedGrantTypes("client_credentials"."refresh_token"."password")
.scopes("server");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// Configure the Token storage mode
endpoints.tokenStore(tokenStore)
// Inject the bean configured with WebSecurityConfig
.authenticationManager(authenticationManager)
// Read the user's authentication information
.userDetailsService(userServiceDetail);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
// Requests for tokens are no longer intercepted
oauthServer.tokenKeyAccess("permitAll()")
// Verify To obtain Token authentication information
.checkTokenAccess("isAuthenticated()"); }}Copy the code
5.5. Start Resource Server
In the application startup class, use the @enableresourceserver annotation to enable the resource service. The application needs to expose the API interface for obtaining the token.
@EnableEurekaClient
@EnableResourceServer
@SpringBootApplication
public class ServiceAuthApplication {
public static void main(String[] args) { SpringApplication.run(ServiceAuthApplication.class, args); }}Copy the code
In this example, RemoteTokenService is used to verify the token. If other resource services need to authenticate tokens, they need to remotely invoke the AUTHENTICATION TOKEN API exposed by the authorization service.
@RestController
@RequestMapping("/users")
public class UserController {
@RequestMapping(value = "/current", method = RequestMethod.GET)
public Principal getUser(Principal principal) {
returnprincipal; }}Copy the code
6. Write the service-hi resource service
6.1. Creating an Application Module
Create a new service-hi module that serves as a resource service. Introduce the following dependencies in the POM.xml file:
<?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>io.github.ostenant.springcloud</groupId>
<artifactId>service-hi</artifactId>
<version>0.0.1 - the SNAPSHOT</version>
<packaging>jar</packaging>
<name>service-hi</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>io.github.ostenant.springcloud</groupId>
<artifactId>spring-cloud-oauth2-example</artifactId>
<version>0.0.1 - the SNAPSHOT</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</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-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Copy the code
6.2. The configuration application. Yml
Configure the OAuth Client information configured in service-auth:
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
server:
port: 8762
spring:
application:
name: service-hi
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/spring-cloud-auth? useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
username: root
password: 123456
jpa:
hibernate:
ddl-auto: update
show-sql: true
security:
oauth2:
resource:
user-info-uri: http://localhost:5000/uaa/users/current Get the user information of the current Token
client:
clientId: service-hi
clientSecret: 123456
accessTokenUri: http://localhost:5000/uaa/oauth/token # access Token
grant-type: client_credentials,password
scope: server
Copy the code
6.3. Configure Resource Server
As a Resource server, the server-HI module needs to configure the Resource Server. The configuration code is as follows:
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfigurer extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// open to the user registered URL
.antMatchers("/user/registry").permitAll() .anyRequest().authenticated(); }}Copy the code
6.4. Configure the OAuth2 Client
@Configuration
@EnableOAuth2Client
@EnableConfigurationProperties
public class OAuth2ClientConfig {
@Bean
@ConfigurationProperties(prefix = "security.oauth2.client")
public ClientCredentialsResourceDetails clientCredentialsResourceDetails(a) {
// Configure the protected resource information
return new ClientCredentialsResourceDetails();
}
@Bean
public RequestInterceptor oauth2FeignRequestInterceptor(a){
// Configure an interceptor that creates an AccessTokenRequest type bean in the Request field for each incoming request.
return new OAuth2FeignRequestInterceptor(
new DefaultOAuth2ClientContext(),
clientCredentialsResourceDetails());
}
@Bean
public OAuth2RestTemplate clientCredentialsRestTemplate(a) {
// Used to request a token from the authentication server service
return newOAuth2RestTemplate(clientCredentialsResourceDetails()); }}Copy the code
6.5. Create a User registration interface
Copy user-java and userRepository. Java from the service-Auth module to the service-hi module. Create a UserService to create a user and encrypt the user password.
UserService.java
@Service
public class UserService {
private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
@Autowired
private UserRepository userRepository;
public User create(String username, String password) {
User user = new User();
user.setUsername(username);
String hash = encoder.encode(password);
user.setPassword(hash);
returnuserRepository.save(user); }}Copy the code
UserController.java
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value = "/registry", method = RequestMethod.POST)
public User createUser(@RequestParam("username") String username,
@RequestParam("password") String password) {
returnuserService.create(username,password); }}Copy the code
6.6. Create a Resource Service Interface
@RestController
public class HiController {
private static final Logger LOGGER = LoggerFactory.getLogger(HiController.class);
@Value("${server.port}")
private String port;
/** * does not require any permissions, as long as the Token in the Header is correct */
@RequestMapping("/hi")
public String hi(a) {
return "hi : " + ",i am from port: " + port;
}
/** * requires the ROLE_ADMIN permission */
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
@RequestMapping("/hello")
public String hello(a) {
return "hello you!";
}
/** * Obtain information about the current authenticated user */
@GetMapping("/getPrinciple")
public OAuth2Authentication getPrinciple(OAuth2Authentication oAuth2Authentication, Principal principal, Authentication authentication){
LOGGER.info(oAuth2Authentication.getUserAuthentication().getAuthorities().toString());
LOGGER.info(oAuth2Authentication.toString());
LOGGER.info("principal.toString()" + principal.toString());
LOGGER.info("principal.getName()" + principal.getName());
LOGGER.info("authentication:" + authentication.getAuthorities().toString());
returnoAuth2Authentication; }}Copy the code
6.6. Configure the startup class of the application
@EnableEurekaClient
@SpringBootApplication
public class ServiceHiApplication {
public static void main(String[] args) { SpringApplication.run(ServiceHiApplication.class, args); }}Copy the code
Start eureka-service, service-auth, and service-hi in sequence.
7. Use PostMan authentication
- To register a user, return the registration success message
- The value is obtained from the authentication server in password mode
token
- Accessing resource Services
/hi
, don’t need permission, justtoken
You can correct
- Accessing resource Services
/hello
, prompt needROLE_ADMIN
permissions
- Failed to access database
role
List, addPermission informationROLE_ADMIN
And then inuser_role
Table association is accessed again
conclusion
There is still room for improvement in this case. For example, add a login interface to the resource server that is not protected by Spring Security. After the login is successful, service-hi remotely invokes auth-service to obtain the token and returns the token to the browser. All subsequent requests of the browser must carry the token.
The drawback of this architecture is that each request requires a remote invocation of the service-Auth service from within the resource service to verify the correctness of the token and the permissions of the user corresponding to the token, adding an additional internal request overhead. If the concurrency is high, service-Auth needs to be deployed in a cluster and needs to be cached. Therefore, the best solution is to use Spring Security OAuth2 and JWT together to realize the authentication and authorization of Spring Cloud microservice system.
reference
- An In-depth Understanding of Spring Cloud and Microservice Construction by Zhipeng Fang
Welcome to pay attention to the technical public number: Zero one Technology Stack
This account will continue to share learning materials and articles on back-end technologies, including virtual machine basics, multithreaded programming, high-performance frameworks, asynchronous, caching and messaging middleware, distributed and microservices, architecture learning and progression.