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>

    至此  我们登录开发完毕

  • 相关阅读:
    SDUT 2143 图结构练习——最短路径 SPFA模板,方便以后用。。 Anti
    SDUT ACM 1002 Biorhythms 中国剩余定理 Anti
    nyist OJ 119 士兵杀敌(三) RMQ问题 Anti
    SDUT ACM 2157 Greatest Number Anti
    SDUT ACM 2622 最短路径 二维SPFA启蒙题。。 Anti
    二叉索引树 区间信息的维护与查询 Anti
    SDUT ACM 2600 子节点计数 Anti
    UVA 1428 Ping pong 二叉索引树标准用法 Anti
    2010圣诞Google首页效果
    Object
  • 原文地址:https://www.cnblogs.com/leiziv5/p/10867987.html
Copyright © 2011-2022 走看看