08账号+密码+图片验证码认证

本文详细描述了如何使用SpringBoot和Feign实现账号密码认证过程,涉及验证码服务的集成、Feign客户端配置、熔断降级策略以及JWT的使用。步骤包括放行特定接口请求、Feign接口定义、Nacos配置管理和后端服务验证逻辑。
摘要由CSDN通过智能技术生成

账号+密码+图片验证码认证

实现步骤

实现账号密码认证,执行流程如下

在这里插入图片描述

第一步: 对于验证码服务工程的生成验证码图片的接口在网关处需要放行,否则页面无法获取生成的验证码图片

/**=临时放行所有请求
/auth/**=认证服务地址
/content/open/**=内容管理公开访问文件接口
/media/open/**=媒资管理公开访问接口

第二步: 在认证服务工程中定义远程调用验证码服务的Feign接口,并在启动类上添加@EnableFeignClients注解

  • 用户输入的验证码后会连同服务端响应的key会一同先提交至认证服务, 然后认证服务携带key和输入的验证码请求验证码服务工程的校验接口
package com.xuecheng.ucenter.feignclient;
@FeignClient(value = "checkcode",fallbackFactory = CheckCodeClientFactory.class)
@RequestMapping("/checkcode")
public interface CheckCodeClient {
    @PostMapping(value = "/verify")
    public Boolean verify(@RequestParam("key") String key,@RequestParam("code") String code);

}

// 编写熔断降级策略
@Slf4j
@Component
public class CheckCodeClientFactory implements FallbackFactory<CheckCodeClient> {
    @Override
    public CheckCodeClient create(Throwable throwable) {
        return new CheckCodeClient() {
            @Override
            public Boolean verify(String key, String code) {
                log.debug("调用验证码服务熔断异常:{}", throwable.getMessage());
                return null;
            }
        };
    }
}
// 扫描交了@FeignClient注解的类
EnableFeignClients(basePackages = "com.xuecheng.ucenter.feignclient")
    @SpringBootApplication
    public class AuthApplication {
        public static void main(String[] args) {
            SpringApplication.run(AuthApplication.class, args);
        }

        @Bean
        RestTemplate restTemplate(){
            RestTemplate restTemplate = new RestTemplate(new OkHttp3ClientHttpRequestFactory());
            return  restTemplate;
        }

    }

第三步: 引入Feign在Nacos的dev环境下的配置文件

spring:
  application:
    name: auth-service
  cloud:
    nacos:
      server-addr: 192.168.101.65:8848
      discovery:
        namespace: dev402
        group: xuecheng-plus-project
      config:
        namespace: dev402
        group: xuecheng-plus-project
        file-extension: yaml
        refresh-enabled: true
        shared-configs:
          - data-id: swagger-${spring.profiles.active}.yaml
            group: xuecheng-plus-common
            refresh: true
          - data-id: logging-${spring.profiles.active}.yaml
            group: xuecheng-plus-common
            refresh: true
            # 引入Feign在Nacos的dev环境下的配置文件
          - data-id: feign-${spring.profiles.active}.yaml
            group: xuecheng-plus-common
            refresh: true

  profiles:
    active: dev

第四步: 在PasswordAuthServiceImpl中增加校验验证码校验密码的判断逻辑

/**
 * 认证Service
 */
public interface AuthService {
    /**
     * 认证方法
     * @param authParamsDto 认证参数
     * @return  用户信息
     */
    XcUserExt execute(AuthParamsDto authParamsDto);
}
@Service("password_authservice")
public class PasswordAuthServiceImpl implements AuthService {
    @Autowired
    XcUserMapper xcUserMapper;
    @Autowired
    PasswordEncoder passwordEncoder;
    @Autowired
    CheckCodeClient checkCodeClient;

    @Override
    public XcUserExt execute(AuthParamsDto authParamsDto) {
        // 获取用户提交的验证码
        String checkcode = authParamsDto.getCheckcode();
        // 获取验证码的key
        String checkcodekey = authParamsDto.getCheckcodekey();
        if (StringUtils.isBlank(checkcode) || StringUtils.isBlank(checkcodekey)){
            throw new RuntimeException("验证码为空");
        }
        // 首先远程调用验证码服务工程的接口校验验证码的正确性
        Boolean verify = checkCodeClient.verify(checkcodekey, checkcode);
        // 验证码输入错误
        if (!verify){
            throw new RuntimeException("验证码输入错误");
        }
        // 验证码正确,获取登陆账号相关信息
        String username = authParamsDto.getUsername();
        // 根据账号去数据库中查询用户是否存在
        XcUser xcUser = xcUserMapper.selectOne(new LambdaQueryWrapper<XcUser>().eq(XcUser::getUsername, username));
        // 用户不存在抛异常
        if (xcUser == null) {
            throw new RuntimeException("账号不存在");
        }
        // 用户存在,获取用户输入的密码
        String passwordForm = authParamsDto.getPassword();
        // 获取数据库中存储的用户密码
        String passwordDb = xcUser.getPassword();
        // 比较密码
        boolean matches = passwordEncoder.matches(passwordForm, passwordDb);
        // 密码不匹配抛异常
        if (!matches) {
            throw new RuntimeException("账号或密码错误");
        }
        // 密码匹配将查询得到的xcUser对象中的数据封装到扩展的xcUserExt对象中并返回
        XcUserExt xcUserExt = new XcUserExt();
        BeanUtils.copyProperties(xcUser, xcUserExt);
        return xcUserExt;
    }
}

HttpClient测试

重启认证服务,测试申请令牌接口注意JSON数据中要带上authType

# 密码模式,账号密码正确,可以成功获取authType,并正确查询到用户信息
POST localhost:53070/auth/oauth/token?client_id=XcWebApp&client_secret=XcWebApp&grant_type=password&username={"username":"yunqing","password":"111111","checkcode":"ZEUY","checkcodekey":"checkcodepre","authType":"password"}

前后端联调

第一步: 使用浏览器访问http://www.51xuecheng.cn/sign.html
在这里插入图片描述

第二步: 如果验证码和密码均正确在右上角可以看到登录的用户信息,并且前端也会把服务端响应的jwt令牌存储在cookie中,若设置不成功先清一下浏览器的缓存

  • 自动登录: 勾选自动登录cookie生成时间为30天,不勾选关闭浏览器窗口后就会自动删除cookie

在这里插入图片描述

// 在控制台手动设置cookie
document.cookie = "jwt=令牌内容"

// 前端设置cookie的代码
login(){
    //转json串
    let usernameJson = JSON.stringify(this.usernamejson)
    console.log(usernameJson)
    this.formdata.username = usernameJson;
    let params = querystringify(this.formdata);
    loginSubmit(params).then(res=>{
        console.log(res)                    // 控制台输出正常
        console.log(res.access_token)       // 控制台输出正常
        if(res&& res.access_token){
            console.log("进入到设置cookie之前")             // 控制台输出正常
            setCookie("jwt","123",30);                      // 无效
            if(this.autologin){
                setCookie('jwt',res.access_token,30)
            }else{
                console.log("进入到setCookie方法上面")     // 控制台输出正常
                setCookie('jwt',"123",0)                    // 无效
            }
            this.$message.success('登录成功')
            if(this.returnUrl){
                top.location=this.returnUrl
            }else{
                top.location='/'
            }
            
        }
    }).catch(error=>{
    if(error&&error.response&&error.response.data&&error.response.data.error_description){
        this.$message.error(error.response.data.error_description)
    }
    this.getCheckCode();
    })
}
// 对应的setCookie方法
function setCookie(name,value,Days){
    if(Days==0){
        document.cookie = name + "="+ escape (value) + ";domain=localhost;expires=0;path=/" ;
    }else{
        var exp = new Date();
        exp.setTime(exp.getTime() + Days*24*60*60*1000);
        document.cookie = name + "="+ escape (value) + ";domain=localhost;expires=" + exp.toGMTString()+";path=/";
    }
}
// logout()调用setCookie方法手动删除设置的jwt令牌
function logout(){
    setCookie('jwt','',-1)
    window.location='/'
}
  • 10
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值