Small knowledge, big challenge! This paper is participating in theEssentials for programmers”Creative activities
This paper has participated inProject DigginTo win the creative gift package and challenge the creative incentive money.
📖 preface
Good attitude, not so tired. In a good mood, all you see is beautiful scenery.Copy the code
"If you can't solve a problem for a while, use this opportunity to see your limitations and put yourself out of order." As the old saying goes, it's easy to let go. If you are distracted by something, learn to disconnect. Cut out the paranoia, the trash in the community, and get rid of the negative energy. Good attitude, not so tired. In a good mood, all you see is beautiful scenery.
🚓Introduction of depend on
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<! -- Freemarker, page rendering engine -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<! -- SpringBoot monitor client -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>${spring-boot-admin.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<! --redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<! Mysql > introduce database password encryption -->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>${jasypt.version}</version>
</dependency>
<! Mysql > insert link dependency
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector}</version>
<scope>provided</scope>
</dependency>
<! - introduction of Druid rely on Java. SQL. SQLFeatureNotSupportedException http://www.vmfor.com/p/101494868463.html-- >
<dependency>
<! -- Automatic configuration -->
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>${common-pool.version}</version>
</dependency>
<! --<dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-micro-spring-boot-starter</artifactId> <version>${knife4j.version}</version> </dependency>-->
<! -- Introduce MybatisPlus dependency -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<! -- Introduce multi-source dependencies -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>${mybatis-plus-dynamic.version}</version>
</dependency>
</dependencies>
Copy the code
1. Enable class addition
@EnableFeignClients
// Enable the API interface for obtaining the token externally
@EnableResourceServer
@EnableDiscoveryClient
Copy the code
2. Create an authorization profileAuthorizationServerConfig.java
According to the official instructions we need to create a configuration class to implement
AuthorizationServerConfigurer
So let’s create a class that inherits its implementation classAuthorizationServerConfigurerAdapter
, the specific code is as follows:
package com.cyj.dream.auth.config;
import com.cyj.dream.auth.entity.SysUser;
import com.cyj.dream.auth.persistence.service.impl.CustomUserServiceImpl;
import com.cyj.dream.core.constant.Constant;
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.authentication.AuthenticationManager;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
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.CompositeTokenGranter;
import org.springframework.security.oauth2.provider.TokenGranter;
import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter;
import org.springframework.security.oauth2.provider.implicit.ImplicitTokenGranter;
import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter;
import org.springframework.security.oauth2.provider.refresh.RefreshTokenGranter;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
import javax.sql.DataSource;
import java.util.*;
import java.util.concurrent.TimeUnit;
/ * * *@Description: Authorization profile *@BelongsProject: DreamChardonnay
* @BelongsPackage: com.cyj.dream.auth.config
* @Author: ChenYongJia
* @CreateTime: 2021-09-30
* @Email: [email protected]
* @Version: 1.0 * /
// Configure the authentication service center
@Configuration / / configuration class
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private BCryptPasswordEncoder passwordEncoder;
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private DataSource dataSource;
@Autowired
private CustomUserServiceImpl userDetailsService;
/**
* accessToken 有效期 2小时
*/
private static final int ACCESS_TOKEN_VALIDITY_SECONDS = 7200 * 12 * 7;
/**
* accessToken 有效期 2小时
*/
private static final int REFRESH_TOKEN_VALIDITY_SECONDS = 7200 * 12 * 7;
TokenStore is stored in redis * <p> *. You can consider whether to store access_tokens in redis ** based on your own business scenario@return* /
@Bean
public TokenStore redisTokenStore(a) {
RedisTokenStore tokenStore = new RedisTokenStore(redisConnectionFactory);
// Redis key prefix --DreamCloud
tokenStore.setPrefix(Constant.tokenPrefix + "_");
return tokenStore;
}
/** * Config client management is JDBC **@param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().withClient("dream").secret(passwordEncoder.encode("c83fb51ff6e807e8805c6dd9d5707365"))
// Entitlement code Callback address in authorization mode
.redirectUris("http://www.baidu.com")
.authorizedGrantTypes("authorization_code"."password"."refresh_token").scopes("all")
.accessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS)
// Authorization type
.refreshTokenValiditySeconds(REFRESH_TOKEN_VALIDITY_SECONDS);
//clients.withClientDetails(new JdbcClientDetailsService(dataSource));
}
/** * Authentication server Endpoints configuration **@return
* @author ChenYongJia
* @date2021/9/30 * /
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer()));
endpoints.authenticationManager(authenticationManager).allowedTokenEndpointRequestMethods(HttpMethod.GET,
HttpMethod.POST, HttpMethod.PUT,
HttpMethod.DELETE)
.tokenEnhancer(tokenEnhancerChain)
// Use Redis to configure tokenStore management
.tokenStore(redisTokenStore()).userDetailsService(userDetailsService)
// Configure the authorization mode
.tokenGranter(tokenGranter(endpoints));
// Configure the tokenServices parameter +
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
// Set the accessToken expiration time
defaultTokenServices.setAccessTokenValiditySeconds((int) TimeUnit.HOURS.toSeconds(2));
// Configure the expiration time of refreshToken
defaultTokenServices.setRefreshTokenValiditySeconds((int) TimeUnit.DAYS.toSeconds(30));
// Set the support for refreshing tokens
defaultTokenServices.setReuseRefreshToken(true);
defaultTokenServices.setSupportRefreshToken(true);
defaultTokenServices.setTokenStore(endpoints.getTokenStore());
defaultTokenServices.setClientDetailsService(endpoints.getClientDetailsService());
defaultTokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
endpoints.tokenServices(defaultTokenServices);
}
/** * Authentication server related interface permission management **@return
* @author ChenYongJia
* @date2021/9/30 * /
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
// Configure to allow form access
security.allowFormAuthenticationForClients()
.tokenKeyAccess("isAuthenticated()")
.checkTokenAccess("permitAll()");
}
/ * * * configure authorization model can also add custom (not write also have default) * * to see AuthorizationServerEndpointsConfigurer getDefaultTokenGranters in method Later add a mobile phone verification code function * *@param endpoints
* @return* /
private TokenGranter tokenGranter(AuthorizationServerEndpointsConfigurer endpoints) {
List<TokenGranter> list = new ArrayList<>();
// Add a refresh token
list.add(new RefreshTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory()));
// Authorization code mode
list.add(new AuthorizationCodeTokenGranter(endpoints.getTokenServices(), endpoints.getAuthorizationCodeServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory()));
// Client credential mode
list.add(new ClientCredentialsTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory()));
// Password mode
list.add(new ResourceOwnerPasswordTokenGranter(authenticationManager, endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory()));
/ / hidden
list.add(new ImplicitTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory()));
return new CompositeTokenGranter(list);
}
/** * Create a token enhancement method to add some additional information that we want to return ourselves **@return* /
@Bean
public TokenEnhancer tokenEnhancer(a) {
return (accessToken, authentication) -> {
final Map<String, Object> additionalInfo = new HashMap<>(2);
additionalInfo.put("license"."SunnyChen-DreamChardonnay");
SysUser user = (SysUser) authentication.getUserAuthentication().getPrincipal();
if(user ! =null) {
additionalInfo.put("userId", user.getSysUserId());
additionalInfo.put("userPhone", user.getSysUserPhone());
additionalInfo.put("userDeptId", user.getSysUserInfoDepartmentId());
}
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
};
}
/** * is used for verification **@return* /
@Bean
AuthenticationManager authenticationManager(a) {
AuthenticationManager authenticationManager = new AuthenticationManager() {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
returndaoAuhthenticationProvider().authenticate(authentication); }};return authenticationManager;
}
/** * is used for verification **@return* /
@Bean
public AuthenticationProvider daoAuhthenticationProvider(a) {
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(userDetailsService);
daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
returndaoAuthenticationProvider; }}Copy the code
3. Since the authorization server is itself a resource server, create a resource configuration as follows
package com.cyj.dream.auth.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
/ * * *@Description: Resource configurator *@BelongsProject: DreamChardonnay
* @BelongsPackage: com.cyj.dream.auth.config
* @Author: ChenYongJia
* @CreateTime: 2021-09-30
* @Email: [email protected]
* @Version: 1.0 * /
@Configuration
// Enable the resource service
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
HTTP. AuthorizeRequests () = HTTP. AuthorizeRequests () = HTTP. AuthorizeRequests () = HTTP. Instead of http.authorizerequests (), * instead uses requestMatchers().antmatchers (""), which is configured with an array of urls that need to be intercepted by the resource interface@param http
* @return void
*/
@Override
public void configure(HttpSecurity http) throws Exception {
http // Configure the resource interface to be protected
.requestMatchers().
antMatchers("/user"."/test/need_token"."/logout"."/remove"."/update"."/test/need_admin"."/test/scope") .and().authorizeRequests().anyRequest().authenticated(); }}Copy the code
4. CreatewebSecurity
configuration
/ * * OK, I want to say more about the configuration of two words: * * 1. First of all, when we want to customize Spring Security we need to inherit from WebSecurityConfigurerAdapter to complete, relevant configuration can rewrite the corresponding * method. 2. We register our CustomUserService Bean here and add our own custom authentication by overriding the configure method. Configure (HttpSecurity HTTP); configure(HttpSecurity HTTP); configure(HttpSecurity HTTP); .anyRequest().authenticated() means that all other requests must be authenticated. ** antMatchers("/admin/**"). HasRole ("ROLE "). * antMatchers("/admin/**")_ADMIN"), you can also set the files in the ADMIN folder to be accessed by multiple roles, * written as follows:.antmatchers ("/ ADMIN /**").hasanyrole ("ROLE_ADMIN","ROLE_USER") * 6. HasIpAddress specifies whether an IP address is allowed to access the admin resource. AntMatchers ("/admin/**").hasipaddress ("210.210.210.210") * 7 For more permission control, see the source code: */Copy the code
The code is as follows:
package com.cyj.dream.auth.config;
import com.cyj.dream.auth.handler.*;
import com.cyj.dream.auth.persistence.service.impl.CustomUserServiceImpl;
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.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/ * * *@Description: WebSecurity configuration *@BelongsProject: DreamChardonnay
* @BelongsPackage: com.cyj.dream.auth.config
* @Author: ChenYongJia
* @CreateTime: 2021-09-30
* @Email: [email protected]
* @Version: 1.0 * /
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserServiceImpl userDetailsService;
/** * Custom login success handler */
@Autowired
private MyAuthenticationSuccessHandler userLoginSuccessHandler;
/** * Custom logon failed handler */
@Autowired
private MyAuthenticationFailureHandler userLoginFailureHandler;
/** * Customizes the logout success handler */
@Autowired
private UserLogoutSuccessHandler userLogoutSuccessHandler;
/** * Custom temporary no permission processor */
@Autowired
private UserAuthAccessDeniedHandler userAuthAccessDeniedHandler;
/** * Customize the unlogged processor */
@Autowired
private UserAuthenticationEntryPointHandler userAuthenticationEntryPointHandler;
@Bean
public BCryptPasswordEncoder passwordEncoder(a) {
return new BCryptPasswordEncoder();
}
@Override
@Bean
public UserDetailsService userDetailsService(a) {
return new CustomUserServiceImpl();
}
/** * Configure login authentication logic */
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService())
.passwordEncoder(passwordEncoder());
}
/** * Grant type ** support password grant type **@returnAuthentication Managed object *@throwsException Indicates authentication Exception information */
@Bean
@Override
public AuthenticationManager authenticationManagerBean(a) throws Exception {
return super.authenticationManagerBean();
}
/** * Security request configuration, where the Security part of the request is passed, Security interception in the resource server configuration * <p> * HTTP Security configuration **@paramHTTP HTTP security object *@throwsException HTTP security Exception information */
@Override
protected void configure(HttpSecurity http) throws Exception {
// Configure allowed requests and cross-domain issues
http.authorizeRequests()
.antMatchers("/webjars/**"."/js/**"."/css/**"."/images/*"."/fonts/**"."/**/*.png"."/**/*.jpg"."/static/**")
// .anyRequest()
.permitAll()
// All requests are accessible, and local development opens the comment on the following line
//.antMatchers("/**").permitAll()
// Requests or resources without permission validation (read from configuration files), local development can, comment out this line
.antMatchers("/login"."/oauth/**")
.permitAll()
.antMatchers("/ * *")
.fullyAuthenticated()
.and()
// Configure the unlogged custom processing class
.httpBasic()
.authenticationEntryPoint(userAuthenticationEntryPointHandler)
.and()
.csrf()
.disable()
// Set the login address
.formLogin()
/ / local
//.loginPage("/login/userLogin")
//.loginProcessingUrl("/login/userLogin")
.loginPage("/login")
// Configure the logon success custom processing class
.successHandler(userLoginSuccessHandler)
// Configure a custom handling class for login failures
.failureHandler(userLoginFailureHandler)
.permitAll()
.and()
// Configure the logout address
.logout()
// /userInfo/loginOutByToken
.logoutUrl("/login/loginOut")
// Configure the user to log in to the custom processing class
.logoutSuccessHandler(userLogoutSuccessHandler)
.and()
// Config does not have permission to customize processing classes
.exceptionHandling()
.accessDeniedHandler(userAuthAccessDeniedHandler)
.and()
// Enable cross-domain
.cors()
.and()
// Cancel cross-site request forgery protection
.csrf().disable();
/*.cors().and() .addFilterAt(ignoreLogoutFilter, LogoutFilter.class); * /
// In order to be able to use iframe embedded page load
http.headers().frameOptions().sameOrigin();
// No session is required based on Token
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Disable caching
http.headers().cacheControl();
}
@Override
public void configure(WebSecurity web) throws Exception {
// Set resources to be ignored
web.ignoring().antMatchers(
"/error"."/v2/api-docs/**"."/favicon.ico"."/css/**"."/js/**"."/images/*"."/fonts/**"."/**/*.png"."/**/*.jpg")
// Do not intercept the configuration of Swagger2
.antMatchers("/templates/**")
.antMatchers("/static/**")
.antMatchers("/webjars/**")
.antMatchers("/swagger-ui.html/**")
.antMatchers("/v2/**")
.antMatchers("/doc.html")
.antMatchers("/api-docs-ext/**")
.antMatchers("/swagger-resources/**"); ; }}Copy the code
5. Create onecontroller
Conduct access tests
package com.cyj.dream.auth.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cyj.dream.auth.entity.SysUser;
import com.cyj.dream.auth.persistence.service.ITbSysUserService;
import com.cyj.dream.core.aspect.annotation.ResponseResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.security.Principal;
/ * * *@Description: User controller *@BelongsProject: DreamChardonnay
* @BelongsPackage: com.cyj.dream.auth.controller
* @Author: ChenYongJia
* @CreateTime: the 2021-09-30 10:40: *@Email: [email protected]
* @Version: 1.0 * /
@Slf4j
@ResponseResult
@RestController
@requestMapping (value = "/authUser", name = "user controller ")
@api (value = "authUser", tags = "user controller ")
public class UserController {
@Autowired
private ITbSysUserService iTbSysUserService;
@apiOperation (" Get user information by name ")
@APIIMPLICITParams ({@APIIMPLICITParam (name = "userName", value = "userName", dataType = "String", Required = true)}) @APIIMPLICITParams ({@APIIMPLICITParam (name = "userName", value = "userName", dataType = "String", Required = true)}
@requestMapping (value = "getByName", method = requestmethod. GET, name = "name ")
public SysUser getByName(@RequestParam(value = "userName") String userName){
LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SysUser::getUsername, userName);
return iTbSysUserService.getOne(wrapper);
}
@apiOperation (" Get authorized user information ")
@APIIMPLICITParams ({@APIIMPLicitParam (name = "principal", value = "current user ", dataType = "Principal", required = true)})
@requestMapping (value = "current", method = requestmethod. GET, name = "")
public Principal user(Principal principal){
// Authorization information
returnprincipal; }}Copy the code
Request with token
Don’t take
token
The request of
With a token, but without the ROLE_ADMIN permission
6. Finally aboutFegin
Call the serviceToken
The problem of loss
In microservices, RestTemplate or Fegin is often used to call between services, which leads to a problem. When we call other services, the token will be lost and we have no permission to access them.
So we need to add some interceptors to take our tokens away. The configuration code for Fegin is as follows:
public class FeignRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
assertattributes ! =null;
HttpServletRequest request = attributes.getRequest();
// Set the request header
Enumeration<String> headerNames = request.getHeaderNames();
if(headerNames ! =null) {
while(headerNames.hasMoreElements()) { String name = headerNames.nextElement(); String value = request.getHeader(name); requestTemplate.header(name, value); }}// Set the request body, in this case mainly to pass access_token
Enumeration<String> parameterNames = request.getParameterNames();
StringBuilder body = new StringBuilder();
if(parameterNames ! =null) {
while (parameterNames.hasMoreElements()) {
String name = parameterNames.nextElement();
String value = request.getParameter(name);
// Add the Token to the request header
if ("access_token".equals(name)) {
requestTemplate.header("authorization"."Bearer " + value);
}
// Add other parameters to the request body
else {
body.append(name).append("=").append(value).append("&"); }}}// Set the request body
if (body.length() > 0) {
// Remove the last ampersand
body.deleteCharAt(body.length() - 1); requestTemplate.body(body.toString()); }}}Copy the code
Then add this interceptor to our Fegin request interceptor:
@Configuration
public class FeignRequestConfiguration {
@Bean
public RequestInterceptor requestInterceptor(a) {
return newFeignRequestInterceptor(); }}Copy the code
7. Spring Security
和 Shiro
Similarities:
1: indicates authentication
2: authorization function
3: encryption function
4: Session management
5: Cache support
6: rememberMe function…….
Difference:
Advantages:
1. Spring Security is developed based on Spring. If the project uses Spring as the basis, it is more convenient to do permissions with Spring Security, while Shiro needs to integrate development with Spring
2. Spring Security has more features than Shiro, such as Security protection
3: The Spring Security community has more resources than Shiro
Disadvantages:
1: Shiro is relatively simple to configure and use, while Spring Security is complicated to get started
2: Shiro has low dependency and does not require any framework or container and can run independently, while Spring Security relies on the Spring container
8. Database tables
-- used in tests that use HSQL
create table oauth_client_details (
client_id VARCHAR(256) PRIMARY KEY,
resource_ids VARCHAR(256),
client_secret VARCHAR(256),
scope VARCHAR(256),
authorized_grant_types VARCHAR(256),
web_server_redirect_uri VARCHAR(256),
authorities VARCHAR(256),
access_token_validity INTEGER,
refresh_token_validity INTEGER,
additional_information VARCHAR(4096),
autoapprove VARCHAR(256));create table oauth_client_token (
token_id VARCHAR(256),
token LONGVARBINARY,
authentication_id VARCHAR(256) PRIMARY KEY,
user_name VARCHAR(256),
client_id VARCHAR(256));create table oauth_access_token (
token_id VARCHAR(256),
token LONGVARBINARY,
authentication_id VARCHAR(256) PRIMARY KEY,
user_name VARCHAR(256),
client_id VARCHAR(256),
authentication LONGVARBINARY,
refresh_token VARCHAR(256));create table oauth_refresh_token (
token_id VARCHAR(256),
token LONGVARBINARY,
authentication LONGVARBINARY
);
create table oauth_code (
code VARCHAR(256), authentication LONGVARBINARY
);
create table oauth_approvals (
userId VARCHAR(256),
clientId VARCHAR(256),
scope VARCHAR(256),
status VARCHAR(10),
expiresAt TIMESTAMP,
lastModifiedAt TIMESTAMP
);
-- customized oauth_client_details table
create table ClientDetails (
appId VARCHAR(256) PRIMARY KEY,
resourceIds VARCHAR(256),
appSecret VARCHAR(256),
scope VARCHAR(256),
grantTypes VARCHAR(256),
redirectUrl VARCHAR(256),
authorities VARCHAR(256),
access_token_validity INTEGER,
refresh_token_validity INTEGER,
additionalInformation VARCHAR(4096),
autoApproveScopes VARCHAR(256));Copy the code
Finally, thank you for your patience after watching, specific requests and some results can be returned to the content of the previous chapter, leaving a “like” collection is your biggest encouragement to me!
🎉 summary:
- For more references, see here:The Blog of Chan Wing Kai
- integration
auth
There are some classes that I didn’t put there, so you can read the article, and I’ll post the code latergit
On convenient everyone reference study ~ - Like the small partner of the blogger can add a concern, a thumbs-up oh, continue to update hey hey!