第一个控制请求的日志打印级别
先看效果图
日志级别配置方式
新增类 public class FeignConfig {/*** NONE【性能最佳,适用于生产】:不记录任何日志(默认值)* BASIC【适用于生产环境追踪问题】:仅记录请求方法、URL、响应状态代码以及执行时间* HEADERS:记录BASIC级别的基础上,记录请求和响应的header。* FULL【比较适用于开发及测试环境定位问题】:记录请求和响应的header、body和元数 据* @return*/@Beanpublic Logger.Level feignLogLevel(){return Logger.Level.FULL;}}
如何配置
接口认证效果图
服务方获取到的信息
消费方发送的信息
在这个过程中,对于请求的接口进行了认证
如果token不对,效果图如下
本次的认证功能需要三个部分,新增认证服务器,服务方加入认证,消费方获取认证token
认证服务器代码
pom文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>jwt.oauth</groupId><artifactId>jwt-oauth-service</artifactId><version>1.0-SNAPSHOT</version><!--spring boot 父启动器依赖--><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.12.RELEASE</version></parent><properties><eureka.version>2.1</eureka.version><web.version>2.1.18.RELEASE</web.version></properties><!--用于整体控制依赖的版本--><dependencyManagement><dependencies><!--spring cloud依赖管理,引入了Spring Cloud的版本--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Hoxton.SR12</version><type>pom</type><scope>import</scope></dependency><!--web依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.0.1.RELEASE</version></dependency><!--lombok依赖--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.16</version></dependency><!--引入security对oauth2的支持--><dependency><groupId>org.springframework.security.oauth</groupId><artifactId>spring-security-oauth2</artifactId><version>2.3.4.RELEASE</version></dependency><dependency><groupId>org.springframework.security.oauth.boot</groupId><artifactId>spring-security-oauth2-autoconfigure</artifactId><version>2.1.11.RELEASE</version></dependency></dependencies></dependencyManagement><dependencies><!--移除tomcat容器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency><!--加入undertow--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-undertow</artifactId></dependency><!--导入spring cloud oauth2依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId><exclusions><exclusion><groupId>org.springframework.security.oauth.boot</groupId><artifactId>spring-security-oauth2-autoconfigure</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.security.oauth.boot</groupId><artifactId>spring-security-oauth2-autoconfigure</artifactId></dependency><!--引入security对oauth2的支持--><dependency><groupId>org.springframework.security.oauth</groupId><artifactId>spring-security-oauth2</artifactId></dependency></dependencies></project>
配置文件
server.port=2002spring.application.name=jwt-oauth #注册到eureka注册中心,如果是注册到集群就用逗号连接多个,单实例写上一个就好 #eureka.client.service-url.defaultZone=http://localhost:8761/eurekalogging.level.jwt.oauth=debug logging.level.web=debug spring.devtools.add-properties=false
java代码部分
package jwt.oauth;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;/*** @Description:* @Author: tutu-qiuxie* @Create: 2024/4/12 10:19*/ @SpringBootApplication public class JwtOauthApplication {public static void main(String[] args) {SpringApplication.run(JwtOauthApplication.class,args);} }package jwt.oauth.config;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.jwt.crypto.sign.MacSigner; 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.AuthorizationServerTokenServices; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; /*** @Description:* @Author: tutu-qiuxie* @Create: 2024/4/12 10:20*/ @Configuration @EnableAuthorizationServer //开启认证服务器功能 public class OauthServerConfiger extends AuthorizationServerConfigurerAdapter {@Autowiredprivate AuthenticationManager authenticationManager;@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {super.configure(security);security.allowFormAuthenticationForClients().tokenKeyAccess("permitAll()").checkTokenAccess("permitAll()");}/*** 客户端详情配置* @param clients* @throws Exception*/@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {super.configure(clients);clients.inMemory().withClient("client_qiuxie").secret("13301455191qiuxieM").resourceIds("loginId").authorizedGrantTypes("password","refresh_token").scopes("all");}/*** 配置token令牌相关* @param endpoints* @throws Exception*/@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {super.configure(endpoints);endpoints.tokenStore(tokenStore()).tokenServices(authorizationServerTokenServices()).authenticationManager(authenticationManager).allowedTokenEndpointRequestMethods(HttpMethod.GET,HttpMethod.GET);}/*** 描述token信息* @return*/public AuthorizationServerTokenServices authorizationServerTokenServices(){DefaultTokenServices tokenServices = new DefaultTokenServices();tokenServices.setSupportRefreshToken(true);tokenServices.setTokenStore(tokenStore());/*** 添加jwt令牌*/tokenServices.setTokenEnhancer(jwtAccessTokenConverter());tokenServices.setAccessTokenValiditySeconds(120);//令牌有效时间30stokenServices.setRefreshTokenValiditySeconds(259200);//刷新令牌有效时间3天return tokenServices;}public TokenStore tokenStore(){return new JwtTokenStore(jwtAccessTokenConverter());}private String sign_key="qiuxie1992";/*** 返回jwt令牌装换器(生成jwt令牌)* @return*/public JwtAccessTokenConverter jwtAccessTokenConverter(){JwtAccessTokenConverter converter = new JwtAccessTokenConverter();/*** 签名秘钥*/converter.setSigningKey(sign_key);/*** 验证使用的秘钥*/converter.setVerifier(new MacSigner(sign_key));return converter;} }package jwt.oauth.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.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;import java.util.ArrayList; /*** @Description:* @Author: tutu-qiuxie* @Create: 2024/4/12 10:21*/ @Configuration public class SecurityConfiger extends WebSecurityConfigurerAdapter {@Autowiredprivate PasswordEncoder passwordEncoder;/*** 注册认证管理器到容器* @return* @throws Exception*/@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}/*** 密码编码器* @return*/@Beanpublic PasswordEncoder passwordEncoder(){return NoOpPasswordEncoder.getInstance();}/*** 处理用户名和密码* @param auth* @throws Exception*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {UserDetails userDetails=new User("admin","13301455191qiuxieM",new ArrayList<>());auth.inMemoryAuthentication().withUser(userDetails).passwordEncoder(passwordEncoder);} }
服务方需要新增信息
<dependency><groupId>org.springframework.security.oauth.boot</groupId><artifactId>spring-security-oauth2-autoconfigure</artifactId><version>2.5.2</version></dependency><!--引入security对oauth2的支持--><dependency><groupId>org.springframework.security.oauth</groupId><artifactId>spring-security-oauth2</artifactId><version>2.5.0.RELEASE</version></dependency>
package com.ip.config;import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.jwt.crypto.sign.MacSigner; 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.TokenStore; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; /*** @Description:* @Author: tutu-qiuxie* @Create: 2024/4/12 10:24*/ @Configuration @EnableResourceServer @EnableWebSecurity public class ResourceServerConfiger extends ResourceServerConfigurerAdapter {@Value("${resourceId}")private String resourceId;@Value("${signKey}")private String signKey;/*** 进行token校验* @param resources* @throws Exception*/@Overridepublic void configure(ResourceServerSecurityConfigurer resources) throws Exception {//jwt令牌resources.resourceId(resourceId).tokenStore(tokenStore()).stateless(true);//无状态设置}public TokenStore tokenStore(){return new JwtTokenStore(jwtAccessTokenConverter());}/*** 返回jwt令牌转换器* @return*/public JwtAccessTokenConverter jwtAccessTokenConverter(){JwtAccessTokenConverter converter = new JwtAccessTokenConverter();/*** 签名秘钥*/converter.setSigningKey(signKey);converter.setVerifier(new MacSigner(signKey));return converter;}/*** 针对api接口进行认证或是不认证* @param http* @throws Exception*/@Overridepublic void configure(HttpSecurity http) throws Exception {http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).and().authorizeRequests().antMatchers("/queryIp/**").authenticated() //这里面的请求都是需要认证的.anyRequest().permitAll(); //其他的请求不认证} }
配置文件信息
消费方对应代码
如果你已经使用了
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency>
可以按照下面的配置
下面给出具体代码,请注意本次代码需要了解一定的微服务知识
package com.java.config;import com.alibaba.fastjson.JSONObject; import com.java.log.MyFeignLogger; import feign.Logger; import feign.RequestInterceptor; import feign.RequestTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate;/*** @Description:* @Author: Yourheart* @Create: 2022/9/16 13:30*/ //@Configuration public class FeignConfig {// @Autowired // private RestTemplate restTemplate;/*** NONE【性能最佳,适用于生产】:不记录任何日志(默认值)* BASIC【适用于生产环境追踪问题】:仅记录请求方法、URL、响应状态代码以及执行时间* HEADERS:记录BASIC级别的基础上,记录请求和响应的header。* FULL【比较适用于开发及测试环境定位问题】:记录请求和响应的header、body和元数 据* @return*/@Beanpublic Logger.Level feignLogLevel(){return Logger.Level.FULL;}@Beanpublic RequestInterceptor requestInterceptor() {return new RequestInterceptor() {@Overridepublic void apply(RequestTemplate template) {// 假设你已经有方法获取到了正确的TokenString accessToken = getToken();template.header("Authorization", "Bearer " + accessToken);}};}private String getToken(){String url = "http://localhost:2002/oauth/token";String clientSecret = "13301455191qiuxieM";String grantType = "password";String username = "admin";String password = "13301455191qiuxieM";String clientId = "client_qiuxie";HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);MultiValueMap<String, String> map= new LinkedMultiValueMap<>();map.add("client_secret", clientSecret);map.add("grant_type", grantType);map.add("username", username);map.add("password", password);map.add("client_id", clientId);HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);RestTemplate restTemplate = new RestTemplate();ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);// 提取返回值中的access_tokenString responseBody = response.getBody();JSONObject jsonObject = JSONObject.parseObject(responseBody);String accessToken = jsonObject.getString("access_token");return accessToken;}}
关于@FeignClient中configuration属性两种方面的介绍就到这里了