当前位置: 首页 > news >正文

郑州做网站优化最好的公司建网站建设

郑州做网站优化最好的公司,建网站建设,公司做一个网站如何定位,企业电子商城网站建设文章目录 一、背景二、微服务架构介绍三、认证服务器1. 数据库创建2. 新建模块3. 导入依赖和配置4. 安全认证配置类 四、认证服务器测试1. AUTHORIZATION_CODE(授权码模式)1. 获取授权码2. 获取JWT 2. CLIENT_CREDENTIALS(客户端凭证模式) 五、Gateway1.…

文章目录

  • 一、背景
  • 二、微服务架构介绍
  • 三、认证服务器
      • 1. 数据库创建
      • 2. 新建模块
      • 3. 导入依赖和配置
      • 4. 安全认证配置类
  • 四、认证服务器测试
      • 1. AUTHORIZATION_CODE(授权码模式)
          • 1. 获取授权码
          • 2. 获取JWT
      • 2. CLIENT_CREDENTIALS(客户端凭证模式)
  • 五、Gateway
      • 1. 引入依赖
      • 2. 添加白名单文件
      • 3. 全局过滤器
      • 4. 获取远程JWKS
      • 5. 校验JWT
      • 6. 测试(如何携带JWT)
  • 六、后记

一、背景

Oauth2停止维护,基于OAuth 2.1OpenID Connect 1.0Spring Authorization Server模块独立于SpringCloud

本文开发环境如下:

Version
Java17
SpringCloud2023.0.0
SpringBoot3.2.1
Spring Authorization Server1.2.1
Spring Security6.2.1
mysql8.2.0

https://spring.io/projects/spring-security#learn
https://spring.io/projects/spring-authorization-server#learn

二、微服务架构介绍

一个认证服务器(也是一个微服务),专门用于颁发JWT。
一个网关(也是一个微服务),用于白名单判断和JWT校验。
若干微服务。

本文的关键在于以下几点:

  • 搭建认证服务器
  • 网关白名单判断
  • 网关验证JWT
  • 认证服务器如何共享公钥,让其余微服务有JWT自校验的能力。
    在这里插入图片描述

三、认证服务器

这里是官方文档https://spring.io/projects/spring-authorization-server#learn
基本上跟着Getting Started写完就可以。

1. 数据库创建

新建一个数据库xc_users
然后执行jar里自带的三个sql
在这里插入图片描述
这一步官方并没有给出,大概因为可以使用内存存储,在简单demo省去了持久化。不建立数据库可能也是可行的,我没试过。

2. 新建模块

新建一个auth模块,作为认证服务器。

3. 导入依赖和配置

<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-oauth2-authorization-server</artifactId></dependency>
server:servlet:context-path: /authport: 63070
spring:application:name: auth-serviceprofiles:active: devdatasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.101.65:3306/xc_users?serverTimezone=UTC&userUnicode=true&useSSL=false&username: rootpassword: 1009

4. 安全认证配置类

@Configuration
@EnableWebSecurity
public class AuthServerSecurityConfig {}

里面包含诸多内容,有来自Spring Security的,也有来自的Spring Authorization Server的。

  1. UserDetailsService 的实例,用于检索用户进行身份验证。
    @Beanpublic UserDetailsService userDetailsService() {UserDetails userDetails = User.withUsername("lisi").password("456").roles("read").build();return new InMemoryUserDetailsManager(userDetails);}
  1. 密码编码器(可选,本文不用)
    @Beanpublic PasswordEncoder passwordEncoder() {// 密码为明文方式return NoOpPasswordEncoder.getInstance();// 或使用 BCryptPasswordEncoder
//         return new BCryptPasswordEncoder();}
  1. 协议端点的 Spring Security 过滤器链
@Bean@Order(1)public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http)throws Exception {OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);http.getConfigurer(OAuth2AuthorizationServerConfigurer.class).oidc(Customizer.withDefaults());	// Enable OpenID Connect 1.0http// Redirect to the login page when not authenticated from the// authorization endpoint.exceptionHandling((exceptions) -> exceptions.defaultAuthenticationEntryPointFor(new LoginUrlAuthenticationEntryPoint("/login"),new MediaTypeRequestMatcher(MediaType.TEXT_HTML)))// Accept access tokens for User Info and/or Client Registration.oauth2ResourceServer((resourceServer) -> resourceServer.jwt(Customizer.withDefaults()));return http.build();}
  1. 用于身份验证的 Spring Security 过滤器链。
    至于哪些要校验身份,哪些不用,根据自己需求写。
@Bean@Order(2)public SecurityFilterChain defaultFilterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests((authorize) ->authorize.requestMatchers(new AntPathRequestMatcher("/actuator/**")).permitAll().requestMatchers(new AntPathRequestMatcher("/login")).permitAll().requestMatchers(new AntPathRequestMatcher("/oauth2/**")).permitAll().requestMatchers(new AntPathRequestMatcher("/**/*.html")).permitAll().requestMatchers(new AntPathRequestMatcher("/**/*.json")).permitAll().requestMatchers(new AntPathRequestMatcher("/auth/**")).permitAll().anyRequest().authenticated()).formLogin(Customizer.withDefaults()).oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter())));return http.build();}
  1. 自定义验证转化器(可选)
    private JwtAuthenticationConverter jwtAuthenticationConverter() {JwtAuthenticationConverter jwtConverter = new JwtAuthenticationConverter();// 此处可以添加自定义逻辑来提取JWT中的权限等信息// jwtConverter.setJwtGrantedAuthoritiesConverter(...);return jwtConverter;}
  1. 用于管理客户端的 RegisteredClientRepository 实例
	@Beanpublic RegisteredClientRepository registeredClientRepository() {RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString()).clientId("XcWebApp")
//                .clientSecret("{noop}XcWebApp").clientSecret("XcWebApp").clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC).authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN).authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).redirectUri("http://www.51xuecheng.cn")
//                .postLogoutRedirectUri("http://localhost:63070/login?logout").scope("all").scope(OidcScopes.OPENID).scope(OidcScopes.PROFILE).scope("message.read").scope("message.write").scope("read").scope("write").clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build()).tokenSettings(TokenSettings.builder().accessTokenTimeToLive(Duration.ofHours(2))  // 设置访问令牌的有效期.refreshTokenTimeToLive(Duration.ofDays(3))  // 设置刷新令牌的有效期.reuseRefreshTokens(true)                   // 是否重用刷新令牌.build()).build();return new InMemoryRegisteredClientRepository(registeredClient);}
  1. 用于对访问令牌进行签名的实例
    @Beanpublic JWKSource<SecurityContext> jwkSource() {KeyPair keyPair = generateRsaKey();RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();RSAKey rsaKey = new RSAKey.Builder(publicKey).privateKey(privateKey).keyID(UUID.randomUUID().toString()).build();JWKSet jwkSet = new JWKSet(rsaKey);return new ImmutableJWKSet<>(jwkSet);}private static KeyPair generateRsaKey() {KeyPair keyPair;try {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");keyPairGenerator.initialize(2048);keyPair = keyPairGenerator.generateKeyPair();}catch (Exception ex) {throw new IllegalStateException(ex);}return keyPair;}
  1. 用于解码签名访问令牌的JwtDecoder 实例
    @Beanpublic JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);}
  1. 用于配置Spring Authorization ServerAuthorizationServerSettings 实例
    @Beanpublic AuthorizationServerSettings authorizationServerSettings() {return AuthorizationServerSettings.builder().build();}

这里可以设置各种端点的路径,默认路径点开builder()即可看到,如下

public static Builder builder() {return new Builder().authorizationEndpoint("/oauth2/authorize").deviceAuthorizationEndpoint("/oauth2/device_authorization").deviceVerificationEndpoint("/oauth2/device_verification").tokenEndpoint("/oauth2/token").jwkSetEndpoint("/oauth2/jwks").tokenRevocationEndpoint("/oauth2/revoke").tokenIntrospectionEndpoint("/oauth2/introspect").oidcClientRegistrationEndpoint("/connect/register").oidcUserInfoEndpoint("/userinfo").oidcLogoutEndpoint("/connect/logout");}

这里我必须吐槽一下,qnmd /.well-known/jwks.json,浪费我一下午。获取公钥信息的端点现在已经替换成了/oauth2/jwks。

四、认证服务器测试

基本上跟着Getting Started走就行。只不过端点的变动相较于Oauth2很大,还有使用方法上不同。

在配置RegisteredClient的时候,我们设置了三种GrantType,这里只演示两种AUTHORIZATION_CODECLIENT_CREDENTIALS

1. AUTHORIZATION_CODE(授权码模式)

1. 获取授权码

用浏览器打开以下网址,

http://localhost:63070/auth/oauth2/authorize?client_id=XcWebApp&response_type=code&scope=all&redirect_uri=http://www.51xuecheng.cn

对应oauth2/authorize端点,后面的参数和当时设置RegisteredClient 保持对应就行。response_type一定是code
进入到登陆表单,输入lisi - 456登陆。
在这里插入图片描述
选择all,同意请求。
在这里插入图片描述
url被重定向到http://www.51xuecheng.cn,并携带一个code,这就是授权码。

http://www.51xuecheng.cn/?code=9AexK_KFH1m3GiNBKsc0FU2KkedM2h_6yR-aKF-wPnpQT5USKLTqoZiSkHC3GUvt-56_ky-E3Mv5LbMeH9uyd-S1UV6kfJO6znqAcCAF43Yo4ifxTAQ8opoPJTjLIRUC
2. 获取JWT

使用apifox演示,postmanidea-http都可以。
localhost:63070/auth服务的/oauth2/token端点发送Post请求,同时需要携带认证信息。
认证信息可以如图所填的方法,也可以放到Header中,具体做法是将客户端ID和客户端密码用冒号(:)连接成一个字符串,进行Base64编码放入HTTP请求的Authorization头部中,前缀为Basic 。比如
Authorization: Basic bXlDbGllbnRJZDpteUNsaWVudFNlY3JldA==

在这里插入图片描述
在这里插入图片描述
得到JWT
在这里插入图片描述

2. CLIENT_CREDENTIALS(客户端凭证模式)

不需要授权码,直接向localhost:63070/auth服务的/oauth2/token端点发送Post请求,同时需要携带认证信息。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、Gateway

至于gateway基础搭建步骤和gateway管理的若干微服务本文不做指导。

相较于auth模块(也就是Authorization Server),gateway的角色是Resource Server
在这里插入图片描述

1. 引入依赖

		<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-oauth2-resource-server</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>

2. 添加白名单文件

resource下添加security-whitelist.properties文件。
写入以下内容

/auth/**=????
/content/open/**=??????????
/media/open/**=??????????

3. 全局过滤器

在全局过滤器中,加载白名单,然后对请求进行判断。

@Component
@Slf4j
public class GatewayAuthFilter implements GlobalFilter, Ordered {//白名单private static List<String> whitelist = null;static {//加载白名单try (InputStream resourceAsStream = GatewayAuthFilter.class.getResourceAsStream("/security-whitelist.properties");) {Properties properties = new Properties();properties.load(resourceAsStream);Set<String> strings = properties.stringPropertyNames();whitelist= new ArrayList<>(strings);} catch (Exception e) {log.error("加载/security-whitelist.properties出错:{}",e.getMessage());e.printStackTrace();}}@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String requestUrl = exchange.getRequest().getPath().value();log.info("请求={}",requestUrl);AntPathMatcher pathMatcher = new AntPathMatcher();//白名单放行for (String url : whitelist) {if (pathMatcher.match(url, requestUrl)) {return chain.filter(exchange);}}}private Mono<Void> buildReturnMono(String error, ServerWebExchange exchange) {ServerHttpResponse response = exchange.getResponse();String jsonString = JSON.toJSONString(new RestErrorResponse(error));byte[] bits = jsonString.getBytes(StandardCharsets.UTF_8);DataBuffer buffer = response.bufferFactory().wrap(bits);response.setStatusCode(HttpStatus.UNAUTHORIZED);response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");return response.writeWith(Mono.just(buffer));}@Overridepublic int getOrder() {return 0;}
}

4. 获取远程JWKS

yml配置中添加jwk-set-uri属性。

spring:security:oauth2:resourceserver:jwt:jwk-set-uri: http://localhost:63070/auth/oauth2/jwks

新建配置类,自动注入JwtDecoder

@Configuration
public class JwtDecoderConfig {@Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}")String jwkSetUri;@Beanpublic JwtDecoder jwtDecoderLocal() {return NimbusJwtDecoder.withJwkSetUri(jwkSetUri).build();}
}

5. 校验JWT

在全局过滤器中补全逻辑。

@Component
@Slf4j
public class GatewayAuthFilter implements GlobalFilter, Ordered {@Lazy@Autowiredprivate JwtDecoder jwtDecoderLocal;@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String requestUrl = exchange.getRequest().getPath().value();log.info("请求={}",requestUrl);AntPathMatcher pathMatcher = new AntPathMatcher();//白名单放行for (String url : whitelist) {if (pathMatcher.match(url, requestUrl)) {return chain.filter(exchange);}}//检查token是否存在String token = getToken(exchange);log.info("token={}",token);if (StringUtils.isBlank(token)) {return buildReturnMono("没有携带Token,没有认证",exchange);}
//        return chain.filter(exchange);try {Jwt jwt = jwtDecoderLocal.decode(token);// 如果没有抛出异常,则表示JWT有效// 此时,您可以根据需要进一步检查JWT的声明log.info("token有效期至:{}", formatInstantTime(jwt.getExpiresAt()));return chain.filter(exchange);} catch (JwtValidationException e) {log.info("token验证失败:{}",e.getMessage());return buildReturnMono("认证token无效",exchange);}}/*** 从请求头Authorization中获取token*/private String getToken(ServerWebExchange exchange) {String tokenStr = exchange.getRequest().getHeaders().getFirst("Authorization");if (StringUtils.isBlank(tokenStr)) {return null;}String token = tokenStr.split(" ")[1];if (StringUtils.isBlank(token)) {return null;}return token;}/*** 格式化Instant时间** @param expiresAt 在到期* @return {@link String}*/public String formatInstantTime(Instant expiresAt) {// 将Instant转换为系统默认时区的LocalDateTimeLocalDateTime dateTime = LocalDateTime.ofInstant(expiresAt, ZoneId.systemDefault());// 定义日期时间的格式DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");// 格式化日期时间并打印return dateTime.format(formatter);}}

6. 测试(如何携带JWT)

携带一个正确的JWTgateway发送请求。
JWT写到HeaderAuthorization字段中,添加前缀Bearer(用空格隔开),向gateway微服务所在地址发送请求。
在这里插入图片描述
gateway日志输出。
在这里插入图片描述

六、后记

颁发JWT都归一个认证服务器管理,校验JWT都归Gateway管理,至于授权,则由各个微服务自己定义。耦合性低、性能较好。

关于授权,可以接着这篇文章。
微服务OAuth 2.1认证授权Demo方案(Spring Security 6)


文章转载自:
http://dinncoventhole.zfyr.cn
http://dinncococcidiostat.zfyr.cn
http://dinncodetail.zfyr.cn
http://dinncohithermost.zfyr.cn
http://dinncostraiten.zfyr.cn
http://dinncocomputistical.zfyr.cn
http://dinncocancrine.zfyr.cn
http://dinncorobotization.zfyr.cn
http://dinncooutmost.zfyr.cn
http://dinnconanjing.zfyr.cn
http://dinncoproclitic.zfyr.cn
http://dinncozpg.zfyr.cn
http://dinncocyclonoscope.zfyr.cn
http://dinncounseen.zfyr.cn
http://dinncoahithophel.zfyr.cn
http://dinncoprehistory.zfyr.cn
http://dinncomaidhood.zfyr.cn
http://dinncoimprovisatrice.zfyr.cn
http://dinncoshandygaff.zfyr.cn
http://dinncovigo.zfyr.cn
http://dinncocopperize.zfyr.cn
http://dinncochintz.zfyr.cn
http://dinncoarachnidan.zfyr.cn
http://dinncocosmogeny.zfyr.cn
http://dinncoguildhall.zfyr.cn
http://dinncoisozyme.zfyr.cn
http://dinncoclinic.zfyr.cn
http://dinncosubserviency.zfyr.cn
http://dinncobiceps.zfyr.cn
http://dinncocampsite.zfyr.cn
http://dinncotundish.zfyr.cn
http://dinncosnowcat.zfyr.cn
http://dinncoragworm.zfyr.cn
http://dinncobaciamano.zfyr.cn
http://dinncobladderwort.zfyr.cn
http://dinncohippologist.zfyr.cn
http://dinncoshovelhead.zfyr.cn
http://dinncoprotonephridium.zfyr.cn
http://dinncoaxon.zfyr.cn
http://dinncogloze.zfyr.cn
http://dinncobushido.zfyr.cn
http://dinncoitinerate.zfyr.cn
http://dinncomammon.zfyr.cn
http://dinncomosey.zfyr.cn
http://dinncorichelieu.zfyr.cn
http://dinncoseltzogene.zfyr.cn
http://dinncoaccent.zfyr.cn
http://dinncodough.zfyr.cn
http://dinncoslummy.zfyr.cn
http://dinncopromotion.zfyr.cn
http://dinncogarnet.zfyr.cn
http://dinncosarcocele.zfyr.cn
http://dinncosmokily.zfyr.cn
http://dinncoforcible.zfyr.cn
http://dinncodraftiness.zfyr.cn
http://dinncophonotype.zfyr.cn
http://dinncogreenbelt.zfyr.cn
http://dinncosharkskin.zfyr.cn
http://dinncoberat.zfyr.cn
http://dinncoexpellant.zfyr.cn
http://dinncoswinish.zfyr.cn
http://dinncorune.zfyr.cn
http://dinncobeemaster.zfyr.cn
http://dinncoknoxville.zfyr.cn
http://dinncocentrosphere.zfyr.cn
http://dinncodigitizer.zfyr.cn
http://dinncotammerkoski.zfyr.cn
http://dinncohypervisor.zfyr.cn
http://dinncoequate.zfyr.cn
http://dinncowearisome.zfyr.cn
http://dinncocryptomeria.zfyr.cn
http://dinncoetiocholanolone.zfyr.cn
http://dinncoantiglobulin.zfyr.cn
http://dinncoplacatory.zfyr.cn
http://dinncodichromism.zfyr.cn
http://dinncomds.zfyr.cn
http://dinncoabask.zfyr.cn
http://dinncorequiem.zfyr.cn
http://dinncotrendiness.zfyr.cn
http://dinncohybridism.zfyr.cn
http://dinncokeylight.zfyr.cn
http://dinncoomt.zfyr.cn
http://dinncomercuric.zfyr.cn
http://dinncoparturition.zfyr.cn
http://dinncotumblerful.zfyr.cn
http://dinncomethuselah.zfyr.cn
http://dinncoarchidiaconate.zfyr.cn
http://dinncovociferator.zfyr.cn
http://dinncocryoextraction.zfyr.cn
http://dinncofuller.zfyr.cn
http://dinncopopulous.zfyr.cn
http://dinncolongirostral.zfyr.cn
http://dinncolysocline.zfyr.cn
http://dinncoronyon.zfyr.cn
http://dinncoaerification.zfyr.cn
http://dinncomannheim.zfyr.cn
http://dinncomastoidal.zfyr.cn
http://dinncoballplayer.zfyr.cn
http://dinncocosign.zfyr.cn
http://dinncohomephone.zfyr.cn
http://www.dinnco.com/news/142072.html

相关文章:

  • 腾讯 微商 网站 建设怎么样把广告做在百度上
  • 重庆农产品价格信息网seo综合查询是什么意思
  • 阿泰勒北京网站建设软文推广代写代发
  • 京东网站建设流程和结构图百度营销登录
  • 租用服务器一般是谁帮助维护网站安全杭州seo联盟
  • 网站突然消失了企业网站优化软件
  • 微商城怎么开通需要多少钱seo是什么技术
  • 找网页模板的网站好中国旺旺(00151) 股吧
  • 花瓣设计网站官网入口网站怎么被百度收录
  • wordpress+浮动播放器seo外包优化网站
  • html5 网站建设方案新乡seo网络推广费用
  • 二维码怎么在网站上做推广甘肃seo网站
  • 福州外贸网站建设推广网络营销的特征和功能
  • 公司网站建设多少费用济南兴田德润评价宁波网站推广找哪家公司
  • 有没有做视频的网站电商运营推广怎么做
  • 网站设计策略品牌推广方案ppt
  • 广州网站建设 易企建站宁德市蕉城区疫情
  • 网站设计建设价格北京朝阳区疫情最新情况
  • 国家企业信用公示官方网站优化技术
  • 有学做美食的网站吗如何开网店
  • 强大的技术团队网站建设今日新闻头条新闻
  • 上海网站建设流增加百度指数的四种方法
  • 这2个代码 找做网站的 安装一下如何策划一个营销方案
  • 便宜的seo网站优化排名上海高端网站建设
  • 做网站前期创建文件夹网站搜索引擎推广
  • 建筑人才网证书挂靠网页优化公司
  • 潍坊网站建设哪里好百度检索入口
  • 西安网站制作工作室兰州seo实战优化
  • 微信开发网站建设程序建立网站需要什么条件
  • 阜阳网站制作公司多少钱如何做网址