springboot +redis+mysql实现登录功能

springboot +redis+mysql实现简单登录功能

一、创建数据库并连接好
  • 创建表名为user

  • 引入mysql需要的依赖

  <!--mybatis_plus依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter
            </artifactId>
            <version>3.5.3.1</version>
        </dependency>
  </dependency>
        <!--mysql驱动依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java
            </artifactId>
        </dependency>
  • 连接好数据库(这里我使用.yml配置的)
spring:
  #数据库连接
  datasource:
    url: jdbc:mysql://localhost:3306/XXXXX?characterEncoding=utf-8&serverTimezone=GMT%2B8
    username: XXXX
    password: XXXXXX
    driver-class-name: com.mysql.cj.jdbc.Driver
  • 接着使用easycode这个插件快速生成controller、dao、entity、service、service.impl、mapper
二、配置RedisConfig(目的存放token等)
  • 引入redis依赖
 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis
     </artifactId>
 </dependency>
  • 配置redis(.ym文件)

    spring 
      data:
        redis:
          host: localhost
          port: 6379
          password: xxxxxx
          #连接超时时间
         #连接池
          pool:
              #最大连接数
              max-active: 200
              #最大等待时间
              max-wait: -1
              #最大空闲连接数
              max-idle: 10
              #最小空闲连接数
              min-idle: 0
          timeout: 2000
          database: 1
    
    
  • redisconfig序列化为了存进去的是JSON格式
@Configuration
public class RedisConfig {
    
    
    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)throws UnknownHostException {
    
    


        RedisTemplate<String,Object> template=new RedisTemplate<>();

        template.setConnectionFactory(redisConnectionFactory);
        //Json序列化配置指的是在将Java对象转换为Json字符串时

        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer=new Jackson2JsonRedisSerializer(Object.class);
        // 创建一个Jackson2JsonRedisSerializer对象,并指定要序列化的Java对象类型为Object.class。这将使得RedisTemplate可以序列化任意类型的Java对象
        ObjectMapper objectMapper=new ObjectMapper();
        // 创建一个ObjectMapper对象,它是Jackson库进行Json序列化和反序列化的核心组件。
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //设置ObjectMapper的可见性规则,使其能够获取和处理Java对象的所有属性,不论其访问修饰符是什么。
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
       //激活默认类型,以便在Json序列化过程中将Java对象的实际类型信息包含在生成的Json字符串中。这样可以在进行反序列化时恢复对象的具体类型。
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
//将配置好的ObjectMapper对象应用于Jackson2JsonRedisSerializer,从而确保RedisTemplate在序列化Java对象时使用指定的配置

        //string序列化
        StringRedisSerializer stringRedisSerializer=new StringRedisSerializer();

        //key序列化
        template.setKeySerializer(stringRedisSerializer);
        //hash的key序列方式
        template.setHashKeySerializer(stringRedisSerializer);

        //value的序列化方式(JSON序列化)
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //hash的序列化方式(JSON序列化)
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}
三、使用Kaptch生成验证码
  • 引入kaptcha依赖
  <!--验证码-->
        <dependency>
            <groupId>com.github.penggle</groupId>
            <artifactId>kaptcha</artifactId>
            <version>2.3.2</version>
        </dependency>
  • 配置kaptcha的文件

@Configuration
public class KaptChaConfig {
    
    

    @Bean
    public Producer kaptChaProducer() {
    
    

        Properties properties = new Properties();

        //边框样式
        properties.setProperty("kaptcha.border", "yes"); //是否边框
        properties.setProperty("kaptcha.border.color", "black"); //边框颜色

        //图片大小
        properties.setProperty("kaptcha.image.width", "100"); //图片长度
        properties.setProperty("kaptcha.image.height", "60"); //图片宽度

        //验证码内容
        properties.setProperty("kaptcha.textproducer.char.string", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"); //验证码内容集合
        properties.setProperty("kaptcha.textproducer.char.length", "4"); //验证码长度
        properties.setProperty("kaptcha.textproducer.char.space", "2"); //验证码间隔
        properties.setProperty("kaptcha.textproducer.font.names", "微软雅黑"); //验证码字体
        properties.setProperty("kaptcha.textproducer.font.size", "32"); //验证码字体大小
        properties.setProperty("kaptcha.textproducer.font.color", "0,0,0"); //验证码字体颜色

        //干扰项
        properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.NoNoise"); //实现类
        properties.setProperty("kaptcha.noise.color", "blue"); //干扰颜色

        //渲染效果
        //水纹 com.google.code.kaptcha.impl.WaterRipple
        //鱼眼 com.google.code.kaptcha.impl.FishEyeGimpy
        //阴影 com.google.code.kaptcha.impl.ShadowGimpy
        properties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.ShadowGimpy");

        //背景图片渲染器
        properties.setProperty("kaptcha.background.impl", "com.google.code.kaptcha.impl.DefaultBackground");
        properties.setProperty("kaptcha.background.clear.from", "251,255,242");
        properties.setProperty("kaptcha.background.clear.to", "202,235,216");

        //文字渲染器
        properties.setProperty("kaptcha.word.impl", "com.google.code.kaptcha.text.impl.DefaultWordRenderer");

        //使用默认图片实现类
        DefaultKaptcha kaptcha = new DefaultKaptcha();
        Config config = new Config(properties);
        kaptcha.setConfig(config);
        return kaptcha;
    }
}

  • 在controller通过请求获取
@Slf4j
@RestController
@Tag(name = "验证码")
public class KaptChaController {
    
    


    @Resource
    Producer kaptChaProducer;
    @GetMapping(value = "/kaptCha",produces = "image/jpeg")
    @Operation(summary = "获取验证码")
    public void getKaptCha(HttpServletRequest request,HttpServletResponse response, HttpSession session){
    
    
        //生成验证码
        String text =kaptChaProducer.createText();
        //生成图片
        BufferedImage image=kaptChaProducer.createImage(text);
        //将验证码存入session
        //session.setAttribute("kaptCha",text);

        //将图片输出给浏览器
        response.setContentType("image/jpeg");

            ServletOutputStream outputStream= null;
            try {
    
    
                outputStream = response.getOutputStream();
                ImageIO.write(image,"jpg",outputStream);
                log.info("验证码:"+text);
                // 刷新输出流
                outputStream.flush();

                // 关闭输出流
                outputStream.close();
            } catch (IOException e) {
    
    
                log.error("验证码获取失败_________验证码获取失败",e.getMessage());
                throw new RuntimeException(e);
            }



    }

}

四、写登录验证功能
1.创建loginController,写controller层(转递给service层)

    @Resource
    private UserService userService;

    @GetMapping("/login")
    @Operation(summary = "登录",description = "登录之后返回token")
    public Result login(LoginMessage loginMessage, HttpServletRequest request){
    
    

        //return userService.login(loginMessage.getUsername(),loginMessage.getPassword(),loginMessage.getCode(),request);
        return userService.login(loginMessage.getUsername(),loginMessage.getPassword(),request);

    }

2.写service层(传递给serviceimpl)
    Result login(String username, String password, HttpServletRequest request);
3.写serviceimpl层(传递给dao层,重要重要!)

    @Override
    public Result login(String username, String password, HttpServletRequest request) {
    
    
        //判断验证码
        //浏览器使用更好
      /*  String kaptCha = (String) request.getSession().getAttribute("kaptCha");
        System.out.println(request.getSession().getAttribute("kaptCha"));
        if (kaptCha == null ||!kaptCha.equals(code)) {
            log.info("验证码"+kaptCha);
            return Result.error("验证码输入错误,请重新输入");
        }*/
        User user = userDao.userLogin(username, password);
        System.out.println(username+password);
        if (user == null) {
    
    
            log.info("用户不存在或密码不正确");
            return Result.error("用户不存在或密码不正确");

        }

        String token = JwtToken.createToken(user.getUsername());

        //存入redis中
         Map<String,String> tokenMap=new HashMap<>();
        tokenMap.put("token",token);
        //redisTemplate.opsForValue().set("userToken",tokenMap);
        //redisTemplate.opsForHash().putAll("userToken", tokenMap);
        redisTemplate.opsForValue().set("userToken",tokenMap.values());
        return Result.success("登录成功", token);
    }
4.写dao层(传递给mapper.xml,如果不使用.xml在dao层用注解实现)
  User userLogin(@Param("username")String username,  String password);
5.到mapper.xml的配置
  <!-- 用户登录 -->
    <select id="userLogin" resultMap="UserMap">
        select
            *
        from user
        where username = #{
    
    username}
    </select>
五、说明提示

我在entity层加上了LoginMessage和Result

//LoginMessage

@Data
@NoArgsConstructor
@AllArgsConstructor
public class LoginMessage {
    
    
 @Schema(description = "用户名",required = true)
 private String username;
 @Schema(description = "密码",required = true)
 private String password;
 /*@Schema(description = "验证码",required = true)
 private String code;*/
}

//Result

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
    
    
    private long code;
    private String message;
    private  Object obj;

    //成功返回结果
    public  static  Result success(String message){
    
    
        return new Result(200,message,null);
    }
    //成功返回结果
    public  static  Result success(String message,Object obj){
    
    
        return new Result(200,message,obj);
    }
    //失败返回结果
    public  static  Result error(String message){
    
    
        return  new Result(500,message,null);
    }
    //失败返回结果
    public  static  Result error(String message,Object obj){
    
    
        return  new Result(500,message,obj);
    }
    //失败返回结果
      Result error(String message){
    
    
        return  new Result(500,message,null);
    }
    //失败返回结果
    public  static  Result error(String message,Object obj){
    
    
        return  new Result(500,message,obj);
    }
    //失败返回结果
}
}

- 为什么加Result?

是为了登录失败或成功时返回一个处理数据得到我想看到的形式

- 以上登录功能的代码中的验证码被我注释了,想要使用需要验证码解开注释和,传递参数时加上string code (controller、service、serviceimpl、entity)

猜你喜欢

转载自blog.csdn.net/m0_63084496/article/details/132000255
今日推荐