96SEO 2026-02-19 18:37 7
注意配置passwordEncoder为BCryptPasswordEncoder

clazz;static{ParserConfig.getGlobalInstance().setAutoTypeSupport(true);}public
SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);}Overridepublic
TypeFactory.defaultInstance().constructType(clazz);}
redisTemplate(RedisConnectionFactory
connectionFactory){RedisTemplateObject,
RedisTemplate();template.setConnectionFactory(connectionFactory);FastJsonRedisSerializer
FastJsonRedisSerializer(Object.class);//
使用StringRedisSerializer来序列化和反序列化redis的key值template.setKeySerializer(new
StringRedisSerializer());template.setValueSerializer(serializer);//
Hash的key也采用StringRedisSerializer的序列化方式template.setHashKeySerializer(new
StringRedisSerializer());template.setHashValueSerializer(serializer);template.afterPropertiesSet();return
设置允许跨域的路径.allowedOriginPatterns(*)
设置允许跨域请求的域名.allowCredentials(true)
跨域允许时间}Bean//使用Bean注入fastJsonHttpMessageConvertpublic
fastJsonHttpMessageConverters()
{//1.需要定义一个Convert转换消息的对象FastJsonHttpMessageConverter
newFastJsonHttpMessageConverter();FastJsonConfig
FastJsonConfig();fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);fastJsonConfig.setDateFormat(yyyy-MM-dd
SerializeConfig.globalInstance.put(Long.class,
ToStringSerializer.instance);fastJsonConfig.setSerializeConfig(SerializeConfig.globalInstance);fastConverter.setFastJsonConfig(fastJsonConfig);HttpMessageConverter?
configureMessageConverters(ListHttpMessageConverter?
{converters.add(fastJsonHttpMessageConverters());}}
renderString(HttpServletResponse
{try{response.setStatus(200);response.setContentType(application/json);response.setCharacterEncoding(utf-8);response.getWriter().print(string);}catch
e){e.printStackTrace();}}public
context.getMimeType(filename);//获取文件的mime类型response.setHeader(content-type,mimeType);String
URLEncoder.encode(filename,UTF-8);response.setHeader(Content-disposition,attachment;
response.setContentType(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet);
response.setCharacterEncoding(utf-8);}
value){redisTemplate.opsForValue().set(key,
timeUnit){redisTemplate.opsForValue().set(key,
redisTemplate.opsForValue();return
redisTemplate.delete(key);}/***
redisTemplate.delete(collection);}/***
redisTemplate.opsForList().rightPushAll(key,
redisTemplate.opsForList().range(key,
dataSet){BoundSetOperationsString,
redisTemplate.boundSetOps(key);IteratorT
(it.hasNext()){setOperation.add(it.next());}return
redisTemplate.opsForSet().members(key);}/***
{redisTemplate.opsForHash().putAll(key,
redisTemplate.opsForHash().entries(key);}/***
value){redisTemplate.opsForHash().put(key,
redisTemplate.opsForHash();return
redisTemplate.opsForHash();hashOperations.delete(key,
redisTemplate.opsForHash().multiGet(key,
UUID.randomUUID().toString().replaceAll(-,
SignatureAlgorithm.HS256;SecretKey
System.currentTimeMillis();Date
Date(nowMillis);if(ttlMillisnull){ttlMillisJwtUtil.JWT_TTL;}long
签发时间.signWith(signatureAlgorithm,
第二个参数为秘钥.setExpiration(expDate);}/***
eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJjYWM2ZDVhZi1mNjVlLTQ0MDAtYjcxMi0zYWEwOGIyOTIwYjQiLCJzdWIiOiJzZyIsImlzcyI6InNnIiwiaWF0IjoxNjM4MTA2NzEyLCJleHAiOjE2MzgxMTAzMTJ9.JVsSbkP94wuczb4QryQbAke3ysBDIL5ou8fWsbt_ebg;Claims
parseJWT(token);System.out.println(claims);}/***
Base64.getDecoder().decode(JwtUtil.JWT_KEY);SecretKey
Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody();}}
blogLoginService;PostMapping(/login)public
blogLoginService.login(user);}}BlogLoginService
super.au***nticationManagerBean();}Autowiredprivate
jwtAu***nticationTokenFilter;Overrideprotected
{http//关闭csrf.csrf().disable()//不通过Session获取SecurityContext.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()//
允许匿名访问.antMatchers(/login).anonymous().antMatchers(/link/getAllLink).au***nticated()//
除上面外的所有请求全部不需要认证即可访问.anyRequest().permitAll();http.logout().disable();http.addFilterBefore(jwtAu***nticationTokenFilter,
UsernamePasswordAu***nticationFilter.class);//允许跨域http.cors();}Beanpublic
au***nticationManager;Autowiredprivate
{UsernamePasswordAu***nticationToken
UsernamePasswordAu***nticationToken(user.getUserName(),user.getPassword());Au***ntication
au***nticationManager.au***nticate(au***nticationToken);//判断是否认证通过if(Objects.isNull(au***nticate)){throw
RuntimeException(用户名或密码错误);}//获取userId
au***nticate.getPrincipal();String
loginUser.getUser().getId().toString();String
JwtUtil.createJWT(userId);//把用户信息存入redisredisCache.setCacheObject(blogLogin:userId,loginUser);//把token和userInfo封装
返回//把User转换UserInfoVOUserInfoVO
BeanCopyUtils.copyBean(loginUser.getUser(),
UserInfoVO.class);BlogUserLoginVO
BlogUserLoginVO(jwt,userInfoVO);return
新建UserDetailServiceImpl实现UserDetailService
注意配置passwordEncoder为BCryptPasswordEncoder
{//根据用户名查询用户信息LambdaQueryWrapperUser
LambdaQueryWrapper();queryWrapper.eq(User::getUserName,username);User
userMapper.selectOne(queryWrapper);//判断是否查到用户
RuntimeException(用户不存在);}//返回用户信息//TODO
user.getPassword();}Overridepublic
user.getUserName();}Overridepublic
doFilterInternal(HttpServletRequest
request.getHeader(token);if(!StringUtils.hasText(token)){//说明该接口不需要登录
直接放行filterChain.doFilter(request,response);return;}//解析获取userIdClaims
token非法//响应告诉前端需要重新登录ResponseResult
ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);WebUtils.renderString(response,
JSON.toJSONString(result));return;}String
claims.getSubject();//从redis中获取用户信息LoginUser
redisCache.getCacheObject(blogLogin:
userId);//如果获取不到if(Objects.isNull(loginUser)){//说明登录过期
ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);WebUtils.renderString(response,
JSON.toJSONString(result));return;}//存入SecurityContextHolderUsernamePasswordAu***nticationToken
UsernamePasswordAu***nticationToken(loginUser,null,null);SecurityContextHolder.getContext().setAu***ntication(au***nticationToken);filterChain.doFilter(request,response);}
super.au***nticationManagerBean();}Autowiredprivate
jwtAu***nticationTokenFilter;Overrideprotected
{http//关闭csrf.csrf().disable()//不通过Session获取SecurityContext.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()//
允许匿名访问.antMatchers(/login).anonymous().antMatchers(/link/getAllLink).au***nticated()//
除上面外的所有请求全部不需要认证即可访问.anyRequest().permitAll();http.logout().disable();http.addFilterBefore(jwtAu***nticationTokenFilter,
UsernamePasswordAu***nticationFilter.class);//允许跨域http.cors();}Beanpublic
目前我们的项目在认证出错或者权限不足的时候响应回来的Json是Security的异常处理结果。
但是这个
响应的格式肯定是不符合我们项目的接口规范的。
所以需要自定义异常处理。
{e.printStackTrace();//InsufficientAu***nticationException//BadCredentialsExceptionResponseResult
BadCredentialsException){result
ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_ERROR.getCode(),e.getMessage());}else
InsufficientAu***nticationException){result
ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);}else
ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR.getCode(),认证或授权失败);}//响应给前端WebUtils.renderString(response,
{e.printStackTrace();ResponseResult
ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH);//响应给前端WebUtils.renderString(response,
super.au***nticationManagerBean();}Autowiredprivate
jwtAu***nticationTokenFilter;AutowiredAu***nticationEntryPoint
au***nticationEntryPoint;AutowiredAccessDeniedHandler
accessDeniedHandler;Overrideprotected
{http//关闭csrf.csrf().disable()//不通过Session获取SecurityContext.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()//
允许匿名访问.antMatchers(/login).anonymous().antMatchers(/link/getAllLink).au***nticated()//
除上面外的所有请求全部不需要认证即可访问.anyRequest().permitAll();//配置异常处理器http.exceptionHandling().au***nticationEntryPoint(au***nticationEntryPoint).accessDeniedHandler(accessDeniedHandler);http.logout().disable();http.addFilterBefore(jwtAu***nticationTokenFilter,
UsernamePasswordAu***nticationFilter.class);//允许跨域http.cors();}Beanpublic
实际我们在开发过程中可能需要做很多的判断校验如果出现了非法情况我们是期望响应对应的提示
的。
但是如果我们每次都自己手动去处理就会非常麻烦。
我们可以选择直接抛出异常的方式然后对异
常进行统一处理。
把异常中的信息封装成ResponseResult响应给前端。
SystemException(AppHttpCodeEnum
{super(httpCodeEnum.getMsg());this.code
httpCodeEnum.getCode();this.msg
{ExceptionHandler(SystemException.class)public
systemExceptionHandler(SystemException
e){//打印异常信息log.error(出现了异常{},e);//从异常对象中获取提示信息封装发返回return
ResponseResult.errorResult(e.getCode(),e.getMsg());}ExceptionHandler(Exception.class)public
e){//打印异常信息log.error(出现了异常{},e);//从异常对象中获取提示信息封装发返回return
ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR.getCode(),e.getMessage());}}
SecurityContextHolder.getContext().getAu***ntication();LoginUser
au***ntication.getPrincipal();//获取userIdLong
loginUser.getUser().getId();//删除redis中的用户信息redisCache.deleteObject(blogLogin:userId);return
要关闭默认的退出登录功能。
并且要配置我们的退出登录接口需要认证才能访问
{http//关闭csrf.csrf().disable()//不通过Session获取SecurityContext.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()//
允许匿名访问.antMatchers(/login).anonymous().antMatchers(/logout).au***nticated().antMatchers(/link/getAllLink).au***nticated()//
除上面外的所有请求全部不需要认证即可访问.anyRequest().permitAll();//配置异常处理器http.exceptionHandling().au***nticationEntryPoint(au***nticationEntryPoint).accessDeniedHandler(accessDeniedHandler);http.logout().disable();http.addFilterBefore(jwtAu***nticationTokenFilter,
UsernamePasswordAu***nticationFilter.class);//允许跨域http.cors();}
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback