Welcome WeChat search public number [Java version of Web project] for resources: Java learning video/design pattern notes/algorithm manual/Java project
Introduction to SpringCloud Security
Spring Cloud Security provides a set of primitives for building secure applications and services that are easy to use. Declarative models that can be extensively configured externally (or centrally) can help implement large, collaborative, remote component systems, often with central identity management services. It’s also very easy to use in service platforms like Cloud Foundry. Based on Spring Boot and Spring Security OAuth2, you can quickly create systems that implement common patterns, such as single sign-on, token relay, and token exchange.
Function:
- Relay SSO tokens from the front-end to the back-end service in the Zuul proxy
- Relay token between resource servers
- Make the Feign client behave like
OAuth2RestTemplate
Interceptor (to get tokens, etc. - Configure downstream authentication in the Zuul agent
Second, single login implementation
1. Make changes based on SpringCloud – Service Registration and Discovery Eureka
Add Spring-Security support:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Add configuration:
server: port: 8082 spring: application: name: eureka-client eureka: client: serviceUrl: defaultZone: http://localhost:8081/eureka/ # fetch - registry: false # register - with - eureka: # false security authentication configuration security: basic: enabled: true
2, start the project, the browser visit: http://localhost:8082/test
Enter the user name and password for authentication. The user name is user. The password will be output to the console when the program starts, as shown in the figure:
After successful login, the browser displays:
test=============8082
3. Configure the MySQL database to achieve authentication
1. Add dependency:
<? The 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. Example. Demo. Security < / groupId > < artifactId > security - oauth2 < / artifactId > < version > 0.0.1 - the SNAPSHOT < / version > < packaging > jar < / packaging > < name > security - oauth2 < / name > < the parent > < the groupId > com. Example. The demo < / groupId > < artifactId > springcloud ws-security < / artifactId > < version > 0.0.1 - the SNAPSHOT < / version > </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> < project. Reporting. OutputEncoding > utf-8 < / project. Reporting. OutputEncoding > < Java version > 1.8 < / Java 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> <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> <dependency> <groupId>org.springframework.boot</groupId> < artifactId > spring - the boot - starter - velocity < / artifactId > < version > 1.1.3. RELEASE < / version > < / dependency > < the dependency > <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</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>
Add configuration file:
Server: port: 8081 spring: application: name: security - oauth2 datasource: url: JDBC: mysql: / / 127.0.0.1:3306 / alan_oauth? allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=true&autoReconnect=true username: root password: admin driver-class-name: com.mysql.jdbc.Driver security: basic: enabled: false
3. Relevant CONFIG configuration files
Create the authorization configuration information class OAuthSecurityConfig.java and declare the implementation of TokenStore and ClientDetails.
package com.example.demo.security.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; 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.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; 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 javax.sql.DataSource; import java.util.concurrent.TimeUnit; Path: / * * * com. Example. Demo. Security. Config * class name: * function: with a description * note: * founder: typ * creation time: 2018/9/26 now * modifier: * modify remarks: * Modification time: */ @Configuration public class OAuthSecurityConfig extends AuthorizationServerConfigurerAdapter{ @Autowired private AuthenticationManager authenticationManager; @Autowired private DataSource dataSource; @Bean public TokenStore tokenStore(){ return new JdbcTokenStore(dataSource); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager); endpoints.tokenStore(tokenStore()); // DefaultTokenServices = 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 days / / endpoints. TokenServices (tokenServices); } @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { //oauthServer.checkTokenAccess("isAuthenticated()"); oauthServer.checkTokenAccess("permitAll()"); oauthServer.allowFormAuthenticationForClients(); } @Bean public ClientDetailsService clientDetails() { return new JdbcClientDetailsService(dataSource); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.withClientDetails(clientDetails()); clients.inMemory() .withClient("client") .secret("secret") .authorizedGrantTypes("authorization_code") .scopes("app"); }}
The security service configuration class OAuthWebConfig.java
package com.example.demo.security.config; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; Path: / * * * com. Example. Demo. Security. Config * class name: * function: with a description * note: * founder: typ * creation time: 2018/9/26 all * modifier: * modify remarks: * Modification time: */ @Configuration public class OAuthWebConfig extends WebSecurityConfigurerAdapter{ @Override public void configure(WebSecurity web) throws Exception { web.ignoring() .antMatchers("/favor.ico"); } @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); }}
Custom Provider calls the class SSOAuthProvider.java
package com.example.demo.security.config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; import org.springframework.stereotype.Component; import java.util.Collections; Path: / * * * com. Example. Demo. Security. Config * class name: * function: with a description * note: * founder: typ * creation time: * the modifier: behold, 2018/9/26 * modify remarks: * Modification time: */ @Component public class SsoAuthProvider implements AuthenticationProvider{ private static final Logger log = LoggerFactory.getLogger(SsoAuthProvider.class); @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { Log.info (" Custom Provider call "); / / / / return a Token object represents landing successful return new UsernamePasswordAuthenticationToken (authentication. GetPrincipal (), authentication.getCredentials(), Collections.<GrantedAuthority>emptyList()); } @Override public boolean supports(Class<? > aClass) { return true; }}
4. Need a redirected Controller class
package com.example.demo.security.controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.SessionAttributes; import java.util.Map; Path: / * * * com. Example. Demo. Security. The controller * class name: * function: with a description * note: * founder: typ * creation time: 2018/9/26 comes * modifier: * modify remarks: * Modification time: */ @RestController @SessionAttributes("authorizationRequest") public class ErrorController { private static final Logger log = LoggerFactory.getLogger(ErrorController.class); @RequestMapping("/oauth/error") public String error(@RequestParam Map<String, String> parameters){ String url = parameters.get("redirect_uri"); Log.info (" Redirect: {}", url); return "redirect:" + url + "? error=1"; }}
Add annotations @ EnableAuthorizationServer 5, start the class
package com.example.demo.security; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.ProviderManager; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; import java.util.Arrays; @SpringBootApplication @EnableAuthorizationServer public class SecurityOauth2Application { public static void main(String[] args) { SpringApplication.run(SecurityOauth2Application.class, args); } @Autowired private AuthenticationProvider authenticationProvider; @Bean public AuthenticationManager authenticationManager(){ return new ProviderManager(Arrays.asList(authenticationProvider)); }}
Create database and related tables
# Host: 127.0.0.1 (Version 5.7.21)
# Date: 2018-09-26 15:17:51
# Generator: MySQL-Front 6.0 (Build 2.20)
#
# Structure for table "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;
#
# Data for table "clientdetails"
#
#
# Structure for table "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;
#
# Data for table "oauth_access_token"
#
#
# Structure for table "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;
#
# Data for table "oauth_approvals"
#
#
# Structure for table "oauth_client_details"
#
DROP TABLE IF EXISTS `oauth_client_details`;
CREATE TABLE `oauth_client_details` (
`client_id` varchar(128) 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;
#
# Data for table "oauth_client_details"
#
INSERT INTO `oauth_client_details` VALUES ('client',NULL,'secret','app','authorization_code','http://www.baidu.com',NULL,NULL,NULL,NULL,NULL);
#
# Structure for table "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;
#
# Data for table "oauth_client_token"
#
#
# Structure for table "oauth_code"
#
DROP TABLE IF EXISTS `oauth_code`;
CREATE TABLE `oauth_code` (
`code` varchar(256) DEFAULT NULL,
`authentication` blob
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
#
# Data for table "oauth_code"
#
#
# Structure for table "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;
#
# Data for table "oauth_refresh_token"
#
Add a piece of data to the OAUTH_CLIENT_DETAILS table
INSERT INTO `oauth_client_details` VALUES ('client',NULL,'secret','app','authorization_code','http://www.baidu.com',NULL,NULL,NULL,NULL,NULL);
Start the project, browser access:
http://localhost:8081/oauth/authorize?client_id=client&response_type=code&redirect_uri=http://www.baidu.com
Clicking Authorize jumps to the Baidu page because the Baidu page is configured in the database.
IV. Ideas of OAuth
OAuth sets an authorization layer between the “client” and the “service provider”. The client cannot log directly into the service provider, only into the authorization layer, which differentiates the user from the client. The client login authorization layer uses a different token than the user’s password. The user can specify the scope and validity of the authorization layer token at the time of login.
After the Client logs on to the authorization layer, the Service Provider opens the Customer’s stored data to the Client based on the scope and validity of the token.
The flow of OAuth 2.0:
(A) After the user opens the client, the client requests the user to grant authorization.
(B) User agrees to grant authorization to Client.
(C) The client applies to the authentication server for a token using the authorization obtained in the previous step.
(D) After authenticating the client, the authentication server confirms that there is no error and agrees to issue the token.
(E) The client uses the token to request a resource from the resource server.
(F) The resource server confirms the correct token and agrees to open the resource to the client.
Of the above six steps, B is the key, that is, how the user can grant authorization to the client. With this authorization, the client can obtain the token and then access the resource with the token.
V. Authorization mode of the client
In order to obtain access tokens, the client must obtain authorization grant from the user.
OAuth 2.0 defines four types of authorization:
- Authorization code Authorization code
- Simplified pattern (implicit)
- Resource Owner Password Credentials
- Client Credentials
1. Authorization code mode
Authorization code is the most complete authorization mode with the most rigorous procedures. Its feature is to interact with the “service provider” authentication server through the client’s back-end server.
Here are the steps:
(A) The user accesses the client, which directs the former to the authentication server.
(B) The user chooses whether to grant authorization to the client.
(C) Assuming that the user gives authorization, the authentication server directs the user to the “Redirection URI” specified by the client, along with an authorization code.
(D) The client receives the authorization code, appends the previous “redirect URI”, and requests the token from the authentication server. This step is done on the server in the background of the client and is not visible to the user.
(E) After verifying the authorization code and the redirect URI, the authentication server sends the Access Token and Refresh Token to the client.
2. Simplify the model
Implicit Grant type is called Implicit Grant type, which is designed to ask an authentication server for a token directly in the browser without going through the server of a third-party application. It bypasses the “authorization code” step, hence the name. All steps are done in the browser, the token is visible to the visitor, and no authentication is required by the client.
Here are the steps:
(A) The client directs the user to the authentication server.
(B) The user decides whether to grant authorization to the client.
(C) Assuming that the user gives authorization, the authentication server directs the user to the “redirect URI” specified by the client and includes the access token in the Hash section of the URI.
(D) The browser sends a request to the resource server that does not include the Hash value received in the previous step.
(E) The resource server returns a web page containing code that retrieves the token in the Hash value.
(F) The browser executes the script obtained in the previous step to extract the token.
(G) The browser sends the token to the client.
3. Password mode
In the Resource Owner Password Credentials Grant, the user provides his or her user name and Password to the client. The client uses this information to request authorization from the service provider.
In this mode, the user must give the client his or her password, but the client must not store the password. This is usually used when users have a high degree of trust in the client, such as when the client is part of an operating system or is produced by a reputable company. The authentication server, on the other hand, should consider using this mode only if other authorization modes cannot be implemented.
Here are the steps:
(A) The user provides the client with A user name and password.
(B) The client sends the user name and password to the authentication server and requests the token from the latter.
(C) After the authentication server confirms that it is correct, it provides the access token to the client.
4. Client mode
Client Credentials Grant means that clients authenticate to “service providers” on their own behalf, not on behalf of the user. Strictly speaking, the client-side pattern is not a problem that the OAuth framework addresses. In this mode, the user registers directly with the client, and the client requests the “service provider” to provide the service in its own name. In fact, there is no authorization problem.
Here are the steps:
(A) The client authenticates to the authentication server and requests an access token.
(B) After the authentication server confirms that it is correct, it provides the access token to the client.
6. Update the token
If the client’s access token has expired when the user accesses it, it will need to apply for a new access token using the Update Token.
The client makes an HTTP request to update the token with the following parameters:
- grantType: Indicates the authorization mode used, where the value is fixed as “REFRESHToken “, required option.
- Refresh_token: Refers to the updated token received earlier. This option is required.
- Scope: Indicates the authorization scope of the application, which cannot exceed the scope of the last application. If omitted, it indicates the same as the last application.
Author: Programmer’s Home
Source: https://www.pianshen.com/arti…
Recent hot article recommended:
SpringCloud micro-service e-commerce project tutorial