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

香港公司网站内地主机seo在线培训

香港公司网站内地主机,seo在线培训,h5编辑软件,世界工厂两种常见的认证方案 基于Session认证 登录状态信息保存在服务器内存中,若访问量增加,单台节点压力会较大集群环境下需要解决集群中的各种服务器登录状态共享问题 解决方案:将登录状态保存的Redis中,从Redis中查找登录状态 基于…

两种常见的认证方案

基于Session认证

  • 登录状态信息保存在服务器内存中,若访问量增加,单台节点压力会较大
  • 集群环境下需要解决集群中的各种服务器登录状态共享问题

在这里插入图片描述

解决方案:将登录状态保存的Redis中,从Redis中查找登录状态

基于Token认证

  • 登录状态保存在客户端,服务器没有存储开销
  • 客户端发起的每个请求自身均携带登录状态,所以即使后台为集群,也不会面临登录状态共享的问题

在这里插入图片描述

Token登录方案

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

登录流程如下
在这里插入图片描述
登录管理使用的三个接口

  • 获取图形验证码,通过easy-captcha依赖引入工具
  • 登录,通过jjwt-api jjwt-impl jjwt-jackson 依赖引入工具
  • 获取登录用户个人信息

为了使得所有受保护的接口增加验证JWT合法性逻辑,通过HandlerInterceptor拦截实现

common模块中,创建JWT工具类

public class JwtUtil{private static SecretKey secretKey = Keys.hmacShaKeyFor("任意复杂字符串大于指定字节数".getBytes());public static String createToken(Long userId,String username){//官方设置用set,自定义设置用claimString jwt = Jwts.builder().setExpiration(new Date(System.currentTimeMillis()+3600000)).setSubject("LOGIN_USER").claim("userId",userId).claim("username",username).signWith(secretKey,SignatureAlgorithm.HS256)//设置签名以及所使用的算法种类.compact();return jwt;}//校验token是否合法public static Claims parseToken(String token){if(token==null){throw new LeaseException(ResultCodeEnum.ADMIN_LOGIN_AUTH);}try{JwtParser jwtParser = JWTS.parserBuilder().setSigningKey(secretKey).build();Jws<Claims> claimsJws = jwtParser.parse(token);return claimsJws.getBody();}catch(ExpiredJwtExpection e){throw new LeaseException(ResultCodeEnum.TOKEN_EXPIRED);}catch(JwtException e){throw new LeaseException(ResultCodeEnum.TOKEN_INVALID);}}
}

①、Controller接口

@Tag(name="后台管理系统登录")
@RestController
@RequestMapping("/admin")
public class LogicController{@Autowiredprivate LoginService service;@Operation(summary="获取图形验证码")@GetMapping("login/captcha")public Result<CaptchaVo> getCaptcha(){CaptchaVo result = servcie.getCaptcha();return Result.ok(result);}@Operation(summary="登录")@GetMapping("login")public Result<String> login(@RequestBody Login loginVo){String jwt = service.login(loginVo);return Result.ok(jwt);}@Operation(summary="获取登录用户个人信息")@GetMapping("info")public Result<SystemUserInfoVo> info(@RequestHeader("access-token") String token){//将请求的某个header绑定到tokenClaims claims = JwtUtil.parseToken(token);Long userId = claims.get("userId",Long.class);SystemUserInfoVo systemUserInfoVo = service.getLoginUserInfoById(userId);return Result.ok(systemUserInfoVo);}
}

②、接口及其实现类

@Service
public class LoginServiceImpl implements LoginService{@Autowiredpirvate String RedisTemplate stringRedisTemplate;@Autowiredprivate SystemUserMapper systemUserMapper;@Overridepublic CaptchaVo getCaptcha(){SpecCaptcha specCaptcha = new SpecCaptcha(130,48,4);String code = specCaptcha.text().toLowerCase();//Redis中的key命名——项目名:功能模块名   admin:loginString key = "admin:login:" + UUID.randomUUID();//后台管理系统登录模块stringRedisTemplate.opsForValue().set(key,code,60,TimeUnit.SECONDS)return new CaptchaVo(specCpatcha.toBase64(),key);}@Overridepublic String login(LoginVo loginVo){if(loginVo.getCaptchaCode()==null){throw new LeaseException(ResultCodeEnum.ADMIN_CAPTCHA_CODE_NOTFOUND);}//从Redis获取保存的验证码String code = stringRedisTemplate.opsForValue().get(loginVo.getCaptchaKey());if(code==null){//验证码过期throw new LeaseException(ResultCodeEnum.ADMIN_CAPTCHA_CODE_EXPIRED);}if(!code.equals(loginVo.getCaptchaCode().toLowerCase())){throw new LeaseException(ResultCodeEnum.ADMIN_CAPTCHA_CODE_ERROR);}//LambdaQueryWrapper<SystemUser> queryWrapper = new LambdaQueryWrapper<>();//queryWrapper.eq(SystemUser::getUsername,loginVo.getUsername());/**由于该接口使用通用查询会导致和实体类的属性注解select=false查询功能,不显示密码字段的冲突该接口出现了空指针异常所以采用自定义查询*///SystemUser systemUser = systemUserMapper.selectOne(queryWrapper);SystemUser systemUser = systemUserMapper.selectOneByUsername(queryWrapper);if(systemUser==null){throw new LeaseException(ResultCodeEnum.ADMIN_ACCOUNT_NOT_EXIST_ERROR);}if(systemUser.getStatus()==BaseStatus.DISABLE){throw new LeaseException(ResultCodeEnum.ADMIN_ACCOUNT_DISABLED_ERROR);}if(systemUser.getPassword().equals(DigestUtils.md5Hex(loginVo.getPassword))){throw new LeaseException(ResultCodeEnum.ADMIN_ACCOUNT_ERROR);}//生成JWTreturn JwtUtil.createToken(systemUser.getId(),systemUser.getUsername());}@Overridepublic SystemUserInfoVo getLoginUserInfoById(Long userId){SystemUser systemUser = systemUserMapper.selectById(userId);SystemUserInfo systemUserInfoVo = new SystemUserInfo();systemUserInfoVo.setName(systemUser.getName());systemUserInfoVo.setAvatarUrl(systemUser.getAvatarUrl());return systemUserInfoVo;}
}

③、为登录之后才能访问的接口增加验证JWT合法性的逻辑(拦截器)

@Component
public class AuthenticationInterceptor implements HandlerInterceptor{//Controller接口之前执行@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResposne response,Object handler)throw Exception{//从请求头获取tokenString token = request.getHeader("access-token");//同前端约定好的键值对JwtUtil.parseToken(token);return true;}
}

注册拦截器

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer{@Autowiredprivate AuthenticationIntercpetor authenticationIntercpetor;@Overridepublic void addInterceptor(InterceptorRegistry registry){registry.addInterceptor(this.authenticationIntercpetor).addPathPatterns("/admin/**")//拦截admin下所有路径.excludePathPatterns("/admin/login/**");}
}

关于拦截器的重复解析(一次在拦截器中,一次是controller接口中)
JwtUtil.parseToken(token)
所以要通过拦截器的解析结果保存起来,由于拦截器限制性,通常将结果保存在ThreadLocal中
在这里插入图片描述

①、在common模块中创建工具类

public class LoginUserHolder{public static ThreadLocal<LoginUser> threadLocal = new ThreadLocal<>();public static void setLoginUser(LoginUser loginUser){threadLocal.set(loginUser);}public static LoginUser getLoginUser(){return threadLocal.get();}public static void clear(){threadLocal.remove();}
}

同时创建LoginUser

@Data
@AllArgsConstrctor
public class LoginUser{private Long userId;private String username;
}

②、修改拦截器

@Component
public class AuthenticationInterceptor implements HandlerInterceptor{@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throw Exception{String token = request.getHeader("access-token");Claims claims = JwtUtil.parseToken(token);Long userId = claims.get("userId",Long.class);String username = claims.get("username",String.class);LoginUserHolder.setLoginUser(new LoginUser(userId,username));return true;}//清理线程池的内容@Overridepublic void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler){LoginUserHolder.clear();}
}

③、改造Controller

@Operation(sumary="获取登录用户个人信息")
@GetMapping("info")
public Result<SystemUserInfoVo> info(){Long userId = LoginUserHolder.getLoginUser().getUserId();SystemUserInfoVo systemUserInfo = service.getLoginUserInfoById(userId);return Result.ok(systemUserInfoVo);
}

手机移动端登录的具体流程

在这里插入图片描述

①、Controller

@Tag(name="登录管理")
@RestController
@RequestMapping("/app/")
public class LoginController{@Autowiredprivate LoginService service;@GetMapping("login/getCode")@Operation(summary="获取短信验证码")public Result getCode(@RequestParam String phone){service.getCode(phone);return Result.ok();}@PostMapping("login")@Operation(summary="登录")public Result<String> login(@RequestBody LoginVo loginVo){return Result.ok()}@GetMapping("info")@Operation(summary="获取登录用户信息")public Result<UserInfoVo> info(){retur Result.ok();}
}

②、service

Ⅰ、登录的service及其实现类

public interface LoginService{void getCode(String phone);
}
@Service
public class LoginServiceImpl implements LoginService{@Autowiredprivate SmsService smsService;@Autowiredprivate StringRedisTemplate redisTemplate;@Overridepublic void getCode(String phone){}
}

Ⅱ、发送短信的service及其实现类

public interface SmsService{void sendCode(String phone,String code);
}
@Service
public class SmsServiceImpl implements SmsService{@Autowiredprivate Client client;@Overridepublic void sendCode(String phone,String code){SendSmsRequest request = new SendSmsRequest();requst.setPhoneNumber(phone);request.setSignName("阿里云短信测试");request.setTemplateCode("SMS_154950909");request.setTemplateParam("{\"code\":\""+code+"\"}");try{client.sendSms(request);}catch(Exception e){throw new RuntimeException(e);}}
}

在这里插入图片描述

调用阿里云短信服务,common模块中依赖:dysmsapi20170525
applicaiton.yml增加:access-key-id(账号) access-key-secret(密码) endpoint
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
对配置类进行映射,common模块中

@Data
@ConfigurationProperties(prefix="aliyun.sms")
public class AliyunSMSProperties{private String accessKeysId;private String accessKeySecret;private String endpoint;
}

将映射到的参数进行创建访问阿里云的客户端配置

@Configuration
@EnableConfigurationProperties(AliyunSMSProperties.class)
@ConditionalOnProperty(name="aliyun.sms.endpoint")//条件注解,放置其他模块没有配置访问参数而报错
public class AliyunSMSConfiguration{@Autowiredprivate AliyunSMSProperties properties;@Beanpublic Client createClient(){Config config = new Config();config.setAccessKeyId(properties.getAccessKeyId());config.setAccessKeySecret(properties.getAccessKeySecret());config.setEndpoint(properties.getEndpoint())try{return new Client(config);}catch(Exception e){throw new RuntimeException(e);}}
}
http://www.zhongyajixie.com/news/48202.html

相关文章:

  • 东莞房地产网站建设国外域名注册平台
  • wordpress 文章名seo网站排名的软件
  • 网站备案 地域百度快照官网登录
  • 阿里云 做网站东莞疫情最新消息今天新增病例
  • 福州网站建设案例优化快速排名公司
  • 东莞网站建设制作公司人民日报今日头条新闻
  • 做营销的一般逛哪些网站电商代运营收费标准
  • 禹州做网站百度网站制作联系方式
  • 网站分享的功能怎么做河南省最新通知
  • 平谷微网站建设seo网络推广到底是做什么的
  • 东莞网站建设功能企业网页设计与推广
  • 东阿网站建设费用方法seo
  • 做美食的网站抚顺网站建设
  • 宣讲家网站两学一做抖音推广佣金平台
  • 在什么文件中加入什么代码告诉搜索引擎蜘蛛网站地图的文件位置?百度关键词排名联系
  • 网站制作报价seo排名软件
  • 聊城阳谷网站建设最新新闻国内大事件
  • 佛山外贸seo惠州seo推广外包
  • 网站规划对网站建设起到南宁网络推广热线
  • 网站做外链的方式长沙seo网络营销推广
  • 保洁公司网站怎么做营销型网站建设步骤
  • vip视频解析网站怎么做b2b国际贸易平台
  • 山东德铭工程建设公司网站企业培训计划
  • 电子商务网站的设计要素cpc广告接单平台
  • 津南网站建设免费推广的网站平台
  • 佛山品牌网站建设报价怎样创建网站
  • 技校十大吃香专业舟山seo
  • php做彩票网站58同城如何发广告
  • jsp动态网站开发案例教程源码做seo推广一年大概的费用
  • 重庆公司网站 技术支持系统优化助手