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

5000人网站开发网站限时抢购怎么做

5000人网站开发,网站限时抢购怎么做,集成wamp访问域名打开tp做的网站,天津电子商务网站建设公司微服务分布式认证授权方案 在分布式授权系统中#xff0c;授权服务要独立成一个模块做统一授权#xff0c;无论客户端是浏览器#xff0c;app或者第三方#xff0c;都会在授权服务中获取权限#xff0c;并通过网关访问资源 OAuth2的四种授权模式 授权码模式 授权服务器将授…微服务分布式认证授权方案 在分布式授权系统中授权服务要独立成一个模块做统一授权无论客户端是浏览器app或者第三方都会在授权服务中获取权限并通过网关访问资源 OAuth2的四种授权模式 授权码模式 授权服务器将授权码AuthorizationCode转经浏览器发送给client客户端拿着授权码向授权服务器索要访问access_token这种模式是四种模式中最安全的一种模式。一般用于Web服务器端应用或第三方的原生App调用资源服务的时候 密码模式 资源拥有者将用户名、密码发送给客户端客户端拿着资源拥有者的用户名、密码向授权服务器请求令牌access_token密码模式使用较多适应于第一方的单页面应用以及第一方的原生App 客户端模式 客户端向授权服务器发送自己的身份信息并请求令牌access_token确认客户端身份无误后将令牌access_token发送给client这种模式是最方便但最不安全的模式。因此这就要求我们对client完全的信任而client本身也是安全的。因此这种模式一般用来提供给我们完全信任的服务器端服务 简化模式 资源拥有者打开客户端客户端要求资源拥有者给予授权它将浏览器被重定向到授权服务器授权服务器将授权码将令牌access_token以Hash的形式存放在重定向uri的fargment中发送给浏览器 spring security 部分请看spring security 认证授权 OAuth2的配置 添加配置类添加EnableAuthorizationServer 注解标注这是一个认证中心继承 AuthorizationServerConfigurerAdapter EnableAuthorizationServer Configuration public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {/*** 令牌存储策略*/Autowiredprivate TokenStore tokenStore;/*** 客户端存储策略这里使用内存方式后续可以存储在数据库*/Autowiredprivate ClientDetailsService clientDetailsService;/*** Security的认证管理器密码模式需要用到*/Autowiredprivate AuthenticationManager authenticationManager;Autowiredprivate JwtAccessTokenConverter jwtAccessTokenConverter;Autowiredprivate OAuthServerAuthenticationEntryPoint authenticationEntryPoint;Autowiredprivate DataSource dataSource;/*** 配置客户端详情并不是所有的客户端都能接入授权服务*/Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {//TODO 暂定内存模式后续可以存储在数据库中更加方便clients.inMemory()//客户端id.withClient(myjszl)//客户端秘钥.secret(new BCryptPasswordEncoder().encode(123))//资源id唯一比如订单服务作为一个资源,可以设置多个.resourceIds(res1)//授权模式总共四种1. authorization_code授权码模式、password密码模式、client_credentials客户端模式、implicit简化模式//refresh_token并不是授权模式.authorizedGrantTypes(authorization_code,password,client_credentials,implicit,refresh_token)//允许的授权范围客户端的权限这里的all只是一种标识可以自定义为了后续的资源服务进行权限控制.scopes(all)//false 则跳转到授权页面.autoApprove(false)//授权码模式的回调地址.redirectUris(http://www.baidu.com);}/*** 令牌管理服务的配置*/Beanpublic AuthorizationServerTokenServices tokenServices() {DefaultTokenServices services new DefaultTokenServices();//客户端端配置策略services.setClientDetailsService(clientDetailsService);//支持令牌的刷新services.setSupportRefreshToken(true);//令牌服务services.setTokenStore(tokenStore);//access_token的过期时间services.setAccessTokenValiditySeconds(60 * 60 * 24 * 3);//refresh_token的过期时间services.setRefreshTokenValiditySeconds(60 * 60 * 24 * 3);//设置令牌增强使用JwtAccessTokenConverter进行转换services.setTokenEnhancer(jwtAccessTokenConverter);return services;}/*** 授权码模式的service使用授权码模式authorization_code必须注入*/Beanpublic AuthorizationCodeServices authorizationCodeServices() {return new JdbcAuthorizationCodeServices(dataSource);//todo 授权码暂时存在内存中后续可以存储在数据库中 // return new InMemoryAuthorizationCodeServices();}/*** 配置令牌访问的端点*/OverrideSuppressWarnings(ALL)public void configure(AuthorizationServerEndpointsConfigurer endpoints) {//将自定义的授权类型添加到tokenGranters中ListTokenGranter tokenGranters new ArrayList(Collections.singletonList(endpoints.getTokenGranter()));tokenGranters.add(new MobilePwdGranter(authenticationManager, tokenServices(), clientDetailsService,new DefaultOAuth2RequestFactory(clientDetailsService)));endpoints//设置异常WebResponseExceptionTranslator用于处理用户名密码错误、授权类型不正确的异常.exceptionTranslator(new OAuthServerWebResponseExceptionTranslator())//授权码模式所需要的authorizationCodeServices.authorizationCodeServices(authorizationCodeServices())//密码模式所需要的authenticationManager.authenticationManager(authenticationManager)//令牌管理服务无论哪种模式都需要.tokenServices(tokenServices())//添加进入tokenGranter.tokenGranter(new CompositeTokenGranter(tokenGranters))//只允许POST提交访问令牌uri/oauth/token.allowedTokenEndpointRequestMethods(HttpMethod.POST);}/*** 配置令牌访问的安全约束*/Overridepublic void configure(AuthorizationServerSecurityConfigurer security) {//自定义ClientCredentialsTokenEndpointFilter用于处理客户端id密码错误的异常OAuthServerClientCredentialsTokenEndpointFilter endpointFilter new OAuthServerClientCredentialsTokenEndpointFilter(security,authenticationEntryPoint);endpointFilter.afterPropertiesSet();security.addTokenEndpointAuthenticationFilter(endpointFilter);security.authenticationEntryPoint(authenticationEntryPoint)//开启/oauth/token_key验证端口权限访问.tokenKeyAccess(permitAll())//开启/oauth/check_token验证端口认证权限访问.checkTokenAccess(permitAll());//一定不要添加allowFormAuthenticationForClients否则自定义的OAuthServerClientCredentialsTokenEndpointFilter不生效 // .allowFormAuthenticationForClients();} } 主要配置点 先配置客户端详细信息ClientDetailService   configure(ClientDetailsServiceConfigurer clients)在配置令牌访问端点需要先配置令牌管理服务和tokenStore表示令牌的存放和管理策略configure(AuthorizationServerEndpointsConfigurer endpoints)  配置加入令牌管理服务和其他oauth2.0需要的管理器和service最后配置访问令牌的约束条件configure(AuthorizationServerSecurityConfigurer security)定义哪些端点可以访问  spring security的配置  定义配置类添加EnableWebSecurity 注解继承WebSecurityConfigurerAdapter Configuration EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter {Autowiredprivate UserDetailsService userDetailsService;Autowiredprivate SmsCodeSecurityConfig smsCodeSecurityConfig;/*** 加密算法*/BeanPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}Overrideprotected void configure(HttpSecurity http) throws Exception {http//注入自定义的授权配置类.apply(smsCodeSecurityConfig).and().authorizeRequests()//注销的接口需要放行.antMatchers(/oauth/logout).permitAll().anyRequest().authenticated().and().formLogin().loginProcessingUrl(/login).permitAll().and().csrf().disable();}Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {//从数据库中查询用户信息auth.userDetailsService(userDetailsService);}/*** AuthenticationManager对象在OAuth2认证服务中要使用提前放入IOC容器中* Oauth的密码模式需要*/OverrideBeanpublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();} } 配置内容 定义加密算法定义查询用户信息方案在oauth2中密码模式会用到授权管理器定义访问策略哪些放行哪些需要授权  JWT令牌配置  不透明令牌则是令牌本身不存储任何信息比如一串UUIDInMemoryTokenStore就类似这种 因此资源服务拿到这个令牌必须调调用认证授权服务的接口进行令牌的校验高并发的情况下延迟很高性能很低 透明令牌本身就存储这部分用户信息比如JWT资源服务可以调用自身的服务对该令牌进行校验解析不必调用认证服务的接口去校验令牌 JwtAccessTokenConverter令牌增强类用于JWT令牌和OAuth身份进行转换内部生成JWT令牌封装进入OAuth2AccessToken对象返回 在gateway中也需要有jwt令牌和tokenstore配置代码相同 /*** * 令牌的配置*/ Configuration public class AccessTokenConfig {/*** 令牌的存储策略*/Beanpublic TokenStore tokenStore() {//使用JwtTokenStore生成JWT令牌return new JwtTokenStore(jwtAccessTokenConverter());}/*** JwtAccessTokenConverter* TokenEnhancer的子类在JWT编码的令牌值和OAuth身份验证信息之间进行转换。* TODO后期可以使用非对称加密*/Beanpublic JwtAccessTokenConverter jwtAccessTokenConverter(){JwtAccessTokenConverter converter new JwtAccessTokenEnhancer();// 设置秘钥converter.setSigningKey(TokenConstant.SIGN_KEY);/** 设置自定义得的令牌转换器从map中转换身份信息* fix(*)修复刷新令牌无法获取用户详细信息的问题*/converter.setAccessTokenConverter(new JwtEnhanceAccessTokenConverter());return converter;}/*** JWT令牌增强继承JwtAccessTokenConverter* 将业务所需的额外信息放入令牌中这样下游微服务就能解析令牌获取*/public static class JwtAccessTokenEnhancer extends JwtAccessTokenConverter {/*** 重写enhance方法在其中扩展*/Overridepublic OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {Object principal authentication.getUserAuthentication().getPrincipal();if (principal instanceof SecurityUser){//获取userDetailService中查询到用户信息SecurityUser user(SecurityUser)principal;//将额外的信息放入到LinkedHashMap中LinkedHashMapString,Object extendInformationnew LinkedHashMap();//设置用户的userIdextendInformation.put(TokenConstant.USER_ID,user.getUserId());//添加到additionalInformation((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(extendInformation);}return super.enhance(accessToken, authentication);}} } gateway认证管理器  JwtAuthenticationManager需要实现ReactiveAuthenticationManager这个接口。 认证管理的作用就是获取传递过来的令牌对其进行解析、验签、过期时间判定  /*** * JWT认证管理器主要的作用就是对携带过来的token进行校验比如过期时间加密方式等* 一旦token校验通过则交给鉴权管理器进行鉴权*/ Component Slf4j public class JwtAuthenticationManager implements ReactiveAuthenticationManager {/*** 使用JWT令牌进行解析令牌*/Autowiredprivate TokenStore tokenStore;Overridepublic MonoAuthentication authenticate(Authentication authentication) {return Mono.justOrEmpty(authentication).filter(a - a instanceof BearerTokenAuthenticationToken).cast(BearerTokenAuthenticationToken.class).map(BearerTokenAuthenticationToken::getToken).flatMap((accessToken - {OAuth2AccessToken oAuth2AccessToken this.tokenStore.readAccessToken(accessToken);//根据access_token从数据库获取不到OAuth2AccessTokenif (oAuth2AccessToken null) {return Mono.error(new InvalidTokenException(无效的token));} else if (oAuth2AccessToken.isExpired()) {return Mono.error(new InvalidTokenException(token已过期));}OAuth2Authentication oAuth2Authentication this.tokenStore.readAuthentication(accessToken);if (oAuth2Authentication null) {return Mono.error(new InvalidTokenException(无效的token));} else {return Mono.just(oAuth2Authentication);}})).cast(Authentication.class);} } gateway 鉴权管理器 经过认证管理器JwtAuthenticationManager认证成功后就需要对令牌进行鉴权如果该令牌无访问资源的权限则不允通过 JwtAccessManager实现ReactiveAuthorizationManager /**** 鉴权管理器 用于认证成功之后对用户的权限进行鉴权* TODO 此处的逻辑从redis中获取对应的uri的权限与当前用户的token的携带的权限进行对比如果包含则鉴权成功* 企业中可能有不同的处理逻辑可以根据业务需求更改鉴权的逻辑**/ Slf4j Component Deprecated public class JwtAccessManager implements ReactiveAuthorizationManagerAuthorizationContext {Autowiredprivate RedisTemplateString,Object redisTemplate;Overridepublic MonoAuthorizationDecision check(MonoAuthentication mono, AuthorizationContext authorizationContext) {//从Redis中获取当前路径可访问角色列表URI uri authorizationContext.getExchange().getRequest().getURI();Object value redisTemplate.opsForHash().get(SysConstant.OAUTH_URLS, uri.getPath());ListString authorities Convert.toList(String.class,value);//认证通过且角色匹配的用户可访问当前路径return mono//判断是否认证成功.filter(Authentication::isAuthenticated)//获取认证后的全部权限.flatMapIterable(Authentication::getAuthorities).map(GrantedAuthority::getAuthority)//如果权限包含则判断为true.any(authorities::contains).map(AuthorizationDecision::new).defaultIfEmpty(new AuthorizationDecision(false));}} gateway security oauth2.0配置 添加EnableWebFluxSecurity注解由于spring cldou gateway使用的Flux因此需要使用EnableWebFluxSecurity注解开启配置SecurityWebFilterChain添加跨域认证异常鉴权配置 Configuration EnableWebFluxSecurity public class SecurityConfig {/*** JWT的鉴权管理器*/Autowiredprivate ReactiveAuthorizationManagerAuthorizationContext accessManager;/*** token过期的异常处理*/Autowiredprivate RequestAuthenticationEntryPoint requestAuthenticationEntryPoint;/*** 权限不足的异常处理*/Autowiredprivate RequestAccessDeniedHandler requestAccessDeniedHandler;/*** 系统参数配置*/Autowiredprivate SysParameterConfig sysConfig;/*** token校验管理器*/Autowiredprivate ReactiveAuthenticationManager tokenAuthenticationManager;Autowiredprivate CorsFilter corsFilter;BeanSecurityWebFilterChain webFluxSecurityFilterChain(ServerHttpSecurity http) throws Exception{//认证过滤器放入认证管理器tokenAuthenticationManagerAuthenticationWebFilter authenticationWebFilter new AuthenticationWebFilter(tokenAuthenticationManager);authenticationWebFilter.setServerAuthenticationConverter(new ServerBearerTokenAuthenticationConverter());http.httpBasic().disable().csrf().disable().authorizeExchange()//白名单直接放行.pathMatchers(ArrayUtil.toArray(sysConfig.getIgnoreUrls(),String.class)).permitAll()//其他的请求必须鉴权使用鉴权管理器.anyExchange().access(accessManager)//鉴权的异常处理权限不足token失效.and().exceptionHandling().authenticationEntryPoint(requestAuthenticationEntryPoint).accessDeniedHandler(requestAccessDeniedHandler).and()// 跨域过滤器.addFilterAt(corsFilter, SecurityWebFiltersOrder.CORS)//token的认证过滤器用于校验token和认证.addFilterAt(authenticationWebFilter, SecurityWebFiltersOrder.AUTHENTICATION);return http.build();} } gateway全局过滤器 校验token并将通过认证授权的请求转发下层服务并将token信息放到请求头中 /*** 1、白名单直接放行* 2、校验token* 3、读取token中存放的用户信息* 4、重新封装用户信息加密成功json数据放入请求头中传递给下游微服务*/ Component Slf4j public class GlobalAuthenticationFilter implements GlobalFilter, Ordered {/*** JWT令牌的服务*/Autowiredprivate TokenStore tokenStore;Autowiredprivate StringRedisTemplate stringRedisTemplate;/*** 系统参数配置*/Autowiredprivate SysParameterConfig sysConfig;Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {String requestUrl exchange.getRequest().getPath().value();//1、白名单放行比如授权服务、静态资源.....if (checkUrls(sysConfig.getIgnoreUrls(),requestUrl)){return chain.filter(exchange);}//2、 检查token是否存在String token getToken(exchange);if (StringUtils.isBlank(token)) {return invalidTokenMono(exchange);}//3 判断是否是有效的tokenOAuth2AccessToken oAuth2AccessToken;try {//解析token使用tokenStoreoAuth2AccessToken tokenStore.readAccessToken(token);MapString, Object additionalInformation oAuth2AccessToken.getAdditionalInformation();//令牌的唯一IDString jtiadditionalInformation.get(TokenConstant.JTI).toString();/**查看黑名单中是否存在这个jti如果存在则这个令牌不能用****/Boolean hasKey stringRedisTemplate.hasKey(SysConstant.JTI_KEY_PREFIX jti);if (hasKey)return invalidTokenMono(exchange);//取出用户身份信息String user_name additionalInformation.get(user_name).toString();//获取用户权限ListString authorities (ListString) additionalInformation.get(authorities);//从additionalInformation取出userIdString userId additionalInformation.get(TokenConstant.USER_ID).toString();JSONObject jsonObjectnew JSONObject();jsonObject.put(TokenConstant.PRINCIPAL_NAME, user_name);jsonObject.put(TokenConstant.AUTHORITIES_NAME,authorities);//过期时间单位秒jsonObject.put(TokenConstant.EXPR,oAuth2AccessToken.getExpiresIn());jsonObject.put(TokenConstant.JTI,jti);//封装到JSON数据中jsonObject.put(TokenConstant.USER_ID, userId);//将解析后的token加密放入请求头中方便下游微服务解析获取用户信息String base64 Base64.encode(jsonObject.toJSONString());//放入请求头中ServerHttpRequest tokenRequest exchange.getRequest().mutate().header(TokenConstant.TOKEN_NAME, base64).build();ServerWebExchange build exchange.mutate().request(tokenRequest).build();return chain.filter(build);} catch (InvalidTokenException e) {//解析token异常直接返回token无效return invalidTokenMono(exchange);}}Overridepublic int getOrder() {return 0;}/*** 对url进行校验匹配*/private boolean checkUrls(ListString urls,String path){AntPathMatcher pathMatcher new AntPathMatcher();for (String url : urls) {if (pathMatcher.match(url,path))return true;}return false;}/*** 从请求头中获取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;}/*** 无效的token*/private MonoVoid invalidTokenMono(ServerWebExchange exchange) {return buildReturnMono(ResultMsg.builder().code(ResultCode.INVALID_TOKEN.getCode()).msg(ResultCode.INVALID_TOKEN.getMsg()).build(), exchange);}private MonoVoid buildReturnMono(ResultMsg resultMsg, ServerWebExchange exchange) {ServerHttpResponse response exchange.getResponse();byte[] bits JSON.toJSONString(resultMsg).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));} }本文参照项目spring-security-oauth2
http://www.sczhlp.com/news/267449/

相关文章:

  • 中小型网站建设资讯找做钢筋笼的活网站
  • 中国建设官方网站登录做网站的请示
  • 新建网站推广给企业东莞建设工程质量网站
  • 软件工程学习日志2025.11.7
  • 11.7
  • 11月6号
  • AE基本流程
  • 谷歌怎么做公司网站攸县做网站的
  • 大学科技园东区 做网站摄影设计思路
  • 建设企业网站收费在线看mv视频网站入口软件下载
  • 南京seo网站排名优化南京做网站哪家最好
  • 广西网站建设推广报价全屋定制自己设计
  • 朝阳免费网站制作wordpress怎么调用多语言包
  • 个人可以做商城网站吗站长统计幸福宝下载
  • 网易企业邮箱怎么切换账号网站做seo优化有什么优势
  • 电商网站方案网站建设教程 第十课 cf战队网站制作教程和源码
  • 南昌珠峰网站建设网站 head关键字 密度 多少字
  • ui素材网站华为商城网站设计分析
  • 哪有那样的网站中国建设人才网信息网住房和城乡建设岗位培训中心
  • 建设购物网站论文网盘网站开发
  • 手机网站与PC网站网站建设 技术 哪些方面
  • 建设银行怀柔支行营业部网站wordpress 显示视频
  • 青岛做网站哪里好免费dns二级域名
  • 通州网站网站建设怎么建设影视网站
  • 广州网站建设方案优化宝塔网站301重定向怎么做
  • 网站改版销售话术哪些在线网站可以做系统进化树
  • wordpress图片站教程徐州网站建设模板
  • 做网站必备软件如何承接设计网站建设
  • 自已做好的网站怎么做后台山东省住房和城乡建设厅官方网站
  • 小米路由 做网站江苏赛孚建设工程有限公司网站