zoukankan      html  css  js  c++  java
  • spring boot 之登录笔记

         在测试平台的开发中,会牵涉到登录内容,页面需要登录后才能访问,所以,对于登录的开发是很有必要的。本文记录我在系统登录的一些自己的做法。

        首先对登录进行设计。

       如下:

        

       1.登录密码输入错误超过次数限制

      2.能够使用用户名密码登录,邮箱密码登录。

     目前登录所有信息都是在数据库存储。后续优化到redis里面。

      使用spring boot+ jpa+durid。数据库mysql。

     数据库设计如下:

    DROP TABLE IF EXISTS `user`;
    CREATE TABLE `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(64) NOT NULL COMMENT '用户名',
      `password` varchar(255) NOT NULL COMMENT '用户密码',
      `email` varchar(64) DEFAULT NULL COMMENT '用户邮箱',
      `status` int(11) NOT NULL DEFAULT '0' COMMENT '状态,1代表删除',
      `admin` int(11) NOT NULL DEFAULT '0' COMMENT '是否是管理员,1代表是管理员',
      `iphone` varchar(20) DEFAULT NULL COMMENT '用户手机号',
      `workid` int(11) NOT NULL DEFAULT '0',
      `token` varchar(255) DEFAULT NULL,
      `errornum` int(2) NOT NULL DEFAULT '0',
      `freeze` int(2) NOT NULL DEFAULT '0',
      `freezetime` datetime DEFAULT NULL,
      PRIMARY KEY (`id`,`username`),
      KEY `username` (`username`),
      KEY `email` (`email`)
    ) ENGINE=InnoDB AUTO_INCREMENT=76 DEFAULT CHARSET=utf8 COMMENT='用户表';

    数据库名称为planone

     数据库创建后,我们去插入数据。

    INSERT INTO `user` VALUES ('1', 'liwanlei', 'lueSGJZetyySpUndWjMBEg==', '952943386@qq.com', '0', '1', '', '1', 'liwanlei_vlywm4en9/IyTI64bLDQEA==', '0', '1', '2019-04-29 16:14:22');
    那么接下来我们去创建工程
    在pom文件增加依赖
    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
            </dependency>
     <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-freemarker</artifactId>
            </dependency>
    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.2.0</version>
            </dependency>
    <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
    <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </dependency>
    <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>1.1.10</version>
            </dependency>
     <dependency>
                <groupId>org.thymeleaf</groupId>
                <artifactId>thymeleaf</artifactId>
            </dependency>
            <dependency>
                <groupId>org.thymeleaf</groupId>
                <artifactId>thymeleaf-spring4</artifactId>
                <version>2.1.6.RELEASE</version>
            </dependency>

    添加依赖后同步更新。

    在application.yaml 进行配置

    spring:
      datasource:
        druid:
          driver-class-name: com.mysql.jdbc.Driver
          url:  jdbc:mysql://localhost:3306/planone?serverTimeZone=UTC&characterEncoding=utf8&useSSL=true
          username:  root
          password: 123456
          initial-size: 10
          max-active: 1000
          min-idle: 10
          max-wait: 60000
          time-between-eviction-runs-millis: 2000
          keep-alive: true
          filter:
            stat:
              slow-sql-millis: 10000
              log-slow-sql: true
          max-evictable-idle-time-millis: 900000
          min-evictable-idle-time-millis: 400000
        thymeleaf:
            cache: false
            suffix: .html
            mode: HTML5
            encoding: UTF-8
            prefix: classpath:/templates/
    server:
      port: 9999

    配置完毕后,我们在resoures 文件新建templates 文件 和static 文件,添加静态页面用。

    那么我们接下来开发后台,首先写的是dao

    @Data
    @DynamicUpdate
    @Entity
    @JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler"})
    public class User implements Serializable {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
        private String username;
        private String password;
        private String email;
        private String iphone;
        private Integer status =0;
        private Integer admin =0;
        private String token;
        private Date freezetime;
        private  Integer errornum=0;
        private  Integer freeze= 0;
    }

    接下来去开发基于JpaRepository数据访问层

    public interface UserRepository extends JpaRepository<User, Integer> {
        User findByUsername(String username);
    
        User findByEmail(String email);
    }
    

      开发server

    public interface UserSerice {
    
        User login(String username, String password);
    
    }
    

      对应的实现类

    @Service
    @Component
    public class UserSericeImpl implements UserSerice {
        @Autowired
        private UserRepository userRepository;
    @Override
        public User login(String username, String password) {
            /*根据邮箱或者用户名登录*/
            User user = userRepository.findByUsername(username);
            if (user != null) {
                user = login_is(user, password, username);
                return user;
            } else {
                User useremail = userRepository.findByEmail(username);
                if (useremail != null) {
                    user = login_is(useremail, password, username);
                    return user;
                }
            }
            throw new PanExection(ResultEmus.USER_NOT_EXIT);
        }
    
      public User login_is(User user, String password, String username) {
            if (user.getStatus().equals(UserEmus.DELETE.getCode())) {
                throw new PanExection(ResultEmus.USER_DELETE);
            }
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                try {
                    if (user.getFreeze().equals(FreezeEmus.DELETE.getCode()) && (new Date().getTime() - format.parse(user.getFreezetime().toString()).getTime() < 6 * 60 * 1000)) {
                        user.setErrornum(0);
                        userRepository.saveAndFlush(user);
                        throw new PanExection(ResultEmus.USER_FREE);
                    }
                } catch (ParseException e) {
                    throw new PanExection(ResultEmus.EXCEPTIONS);
                }
    
            } catch (NullPointerException e) {
                userRepository.saveAndFlush(user);
            }
            Boolean b = null;
            try {
                b = MD5Until.checkoutpassword(password, user.getPassword());
            } catch (Exception e) {
                throw new PanExection(ResultEmus.EXCEPTIONS);
            }
            if (b) {
                user.setErrornum(0);
                user.setFreezetime(null);
                Date date = new Date();
                String tokne = null;
                tokne = (String) userredis(redisTemplate).opsForValue().get(user.getUsername());
                if (tokne == null) {
                    try {
                        tokne = MD5Until.md5(user.getUsername() + date.toString());
                    } catch (Exception e) {
                        throw new PanExection(ResultEmus.EXCEPTIONS);
                    }
                    String token = user.getUsername() + "_" + tokne;
                    user.setToken(token);
                    userRepository.saveAndFlush(user);
                    userredis(redisTemplate).opsForValue().set(username, token, 1, TimeUnit.DAYS);
                }
                return user;
            } else {
                if (user.getErrornum() > 4) {
                    user.setErrornum(user.getErrornum() + 1);
                    user.setFreeze(FreezeEmus.DELETE.getCode());
                    user.setFreezetime(new Date());
                    userRepository.saveAndFlush(user);
                    throw new PanExection(ResultEmus.USER_FREE);
                } else {
                    Integer err = user.getErrornum() + 1;
                    user.setErrornum(err);
                    userRepository.saveAndFlush(user);
                    throw new PanExection(ResultEmus.USER_ERROR_PASSWORD);
                }
            }
        }
    }
    

      

    ResultEmus.java
    
    @Getter
    public enum ResultEmus {
        SUCCESS_REQUEST(0, "成功"),
        USER_NOT_EXIT(1, "用户不存在"),
        USER_BIND(2, "用户已经绑定"),
        USER_DELETE(3, "用户已经删除"),
        EXCEPTIONS(4, "转化异常"),
        USER_ERROR_PASSWORD(225, "密码错误"),
        USER_ERRPOR_EMAIL(6, "邮箱不匹配"),
        PARM_ERROR(7, "参数错误"),
        USER_EXIT(8, "用户已经存在")
      ;
        private Integer code;
        private String message;
    
        ResultEmus(Integer code, String message) {
            this.code = code;
            this.message = message;
        }
    }
    
    MD5Until.java
    
    public class MD5Until {
        public static String md5(String text) throws Exception {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            BASE64Encoder base64en = new BASE64Encoder();
            String newstr = base64en.encode(md5.digest(text.getBytes()));
            return newstr;
        }
    
        public static boolean checkoutpassword(String password, String oldpassword) throws Exception {
            return md5(password).equals(oldpassword);
        }
    
    }
    

      

      

    开发完server端,我们去写controller

    @RestController
    @RequestMapping("/plan")
    public class LoginContorl {
        @Autowired
        private UserSerice userSerice;
    @GetMapping("/logins")
        public ModelAndView login(ModelAndView modelAndView) {
            modelAndView.setViewName("login");
            return modelAndView;
        }
    
        @PostMapping("/logins")
        public ModelAndView login(ModelAndView modelAndView, @Valid UserForm userVo, BindingResult bindingResult,
                                  HttpServletRequest httpServletRequest) {
    
            HttpSession session = httpServletRequest.getSession();
            if (bindingResult.hasErrors()) {
                modelAndView.addObject("error", bindingResult.getFieldError().getDefaultMessage());
                modelAndView.setViewName("/plan/logins");
                return modelAndView;
            }
            String userName = userVo.getUsername();
            String password = userVo.getPassword();
            try {
                User user = userSerice.login(userName, password);
                session.setMaxInactiveInterval(3600);
                session.setAttribute("userid", user.getId());
                session.setAttribute("username", user.getUsername());
                return new ModelAndView("redirect:/web/index");
            } catch (PanExection e) {
                modelAndView.addObject("error", e.getMessage());
                modelAndView.setViewName("login");
                return modelAndView;
            }
        }
    }

    那么我们需要去写对应的html

    html写在templates   ,login接口如下

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <title>AutoTestPlatform</title>
    
        <link rel="stylesheet" th:href="@{/css/style.css}" href="../static/css/style.css">
    
        <link rel="shortcut icon" th:href="@{/images/favicon.png}" href="../static/images/favicon.png" />
    </head>
    
    <body>
    <div class="body-wrapper">
        <div class="page-wrapper">
            <main class="content-wrapper auth-screen">
                <div class="mdc-layout-grid">
                    <div class="mdc-layout-grid__inner">
                        <div class="mdc-layout-grid__cell stretch-card mdc-layout-grid__cell--span-4">
                        </div>
                        <div class="mdc-layout-grid__cell stretch-card mdc-layout-grid__cell--span-4">
                            <div class="mdc-card">
                                <section class="mdc-card__primary bg-white">
                                    <form th:action="@{/plan/logins}" method="post">
                                        <div>
                                            <!--/*@thymesVar id="error" type=""*/-->
                                            <span id="basic-addon0"> </span>
                                            <span style="font-size: 12px;color: red" th:text="${error}" aria-describedby="basic-addon0"></span>
                                            <br />
                                        </div>
                                        <div class="mdc-layout-grid">
                                            <div class="mdc-layout-grid__inner">
                                                <div class="mdc-layout-grid__cell stretch-card mdc-layout-grid__cell--span-12">
                                                    <label class="mdc-text-field w-100">
                                                        用户名<input type="username"name="username" class="mdc-text-field__input">
    
                                                        <div class="mdc-text-field__bottom-line"></div>
                                                    </label>
                                                </div>
                                                <div class="mdc-layout-grid__cell stretch-card mdc-layout-grid__cell--span-12">
                                                    <label class="mdc-text-field w-100">
                                                        密码<input type="password" name="password" class="mdc-text-field__input">
    
                                                        <div class="mdc-text-field__bottom-line"></div>
                                                    </label>
                                                </div>
    
                                                <div class="mdc-layout-grid__cell stretch-card mdc-layout-grid__cell--span-6 d-flex align-item-center justify-content-end">
                                                    <a th:href="@{/plan/rebackpassword}">忘记密码</a>
                                                </div>
                                                <div class="mdc-layout-grid__cell stretch-card mdc-layout-grid__cell--span-6 d-flex align-item-center justify-content-end">
                                                    <a th:href="@{/plan/reg}">注册</a>
                                                </div>
                                                <div class="mdc-layout-grid__cell stretch-card mdc-layout-grid__cell--span-12">
                                                    <button class="mdc-button mdc-button--raised w-100" data-mdc-auto-init="MDCRipple">
                                                        登录
                                                    </button>
                                                </div>
                                            </div>
                                        </div>
                                    </form>
                                </section>
                            </div>
                        </div>
                        <div class="mdc-layout-grid__cell stretch-card mdc-layout-grid__cell--span-4">
                        </div>
                    </div>
                </div>
            </main>
        </div>
    </div>
    <!-- body wrapper -->
    <!-- plugins:js -->
    <script src="../../node_modules/material-components-web/dist/material-components-web.min.js"></script>
    <script src="../../node_modules/jquery/dist/jquery.min.js"></script>
    <!-- endinject -->
    <!-- Plugin js for this page-->
    <!-- End plugin js for this page-->
    <!-- inject:js -->
    <script src="../../js/misc.js"></script>
    <script src="../../js/material.js"></script>
    <!-- endinject -->
    <!-- Custom js for this page-->
    <!-- End custom js for this page-->
    </body>
    
    </html>
    

      

    这样我们整个界面就开发完毕,我们进行调试测试

     前面插入的数据是 liwanlei  密码是:111111

    登录后跳转到首页

    补充首页代码

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <title>AutoTestPlatform</title>
    </head>
    <h1>hello</h1>
    <body>

    至此  我们登录开发完毕

  • 相关阅读:
    sosex !mk
    使用boost iostream写文件
    编译ios版本的ffmpeg0.11.1
    转换日期为中文数字
    sosex !muf查看方法的反汇编代码
    Xcode 4.5.2 + iOS 6.0免证书(iDP)开发+真机调试+生成IPA全攻略
    sosex查看变量的命令!mdt
    vs2012编译openssl
    为ios编译openssl
    打开的页面关闭后刷新主页面
  • 原文地址:https://www.cnblogs.com/leiziv5/p/10867987.html
Copyright © 2011-2022 走看看