栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

49:第五章:开发admin管理服务:2:开发【管理员登录】接口;(Spring Security的BCrypt密码哈希;token存到redis中;设置cookie;BO实体类接收参数;参数校验;)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

49:第五章:开发admin管理服务:2:开发【管理员登录】接口;(Spring Security的BCrypt密码哈希;token存到redis中;设置cookie;BO实体类接收参数;参数校验;)

说明:

(1)本篇博客内容:开发【管理员登录】接口;

目录

一:管理员账户(包括admin_user表),简述;

1.admin_user表,简介; 

2.直接去数据库,手动创建一个admin管理员账户; 

二:开发管理员登录:Dao、Service部分;

1.根据admin_user表,生成【实体类、mapper接口、mapper.xml】;

2.在【imooc-news-dev-service-admin】管理服务中,创建管理员登录的Service部分;

(1)创建AdminUserService接口,定义【根据"管理员用户名",查询管理员用户】的方法;

(2)创建AdminUserServiceImpl实现类,去实现【根据"管理员用户名",查询管理员用户】方法;

三:开发管理员登录:Controller部分;

1.首先,在【api】接口工程中,定义AdminMngControllerApi接口,并定义【管理员登录】接口;

2.然后,在【admin】管理服务工程中,定义AdminMngController类,去实现AdminMngControllerApi接口;实现【管理员登录】接口;

四:效果;


一:管理员账户(包括admin_user表),简述;

1.admin_user表,简介; 

针对admin用户,我们单独创建了一张表,而没有和普通用户公用一张表;

说明:

(1)MongoDB中有GridFS(GridFS是一种将大型文件存储在MongoDB的文件规范);我们的人脸入库信息,也是一个文件,我们可以把这个文件上传到MongoDB中去

(2)admin_name管理人员的姓名,一般需要是真实姓名;

(3)admin后台管理服务,没有注册功能;而是有一个"账号预分配"的概念;

          ● 即,我们会手动创建admin账号,然后再通过这个admin账号再去创建其他的admin账号;

          ● 所以,在下一部分,我们按照我们这个项目的"管理员用户的密码的加密逻辑",直接去数据库手动创建一个admin账号;

2.直接去数据库,手动创建一个admin管理员账户; 

(1)以前,自己使用过的密码加密方式是MD5加密;可以参考【Spring Boot电商项目18:用户模块七:使用MD5,对密码进行保护;】;这篇博客,也总结了以前遇到过的所有使用MD5加密的情况;

(2)这儿我们采用的加密方式是密码哈希;有关密码哈希的内容,可以先参考【附加:MD5算法原理;BCrypt密码哈希;】;

然后,可以在程序中,单独创建一个类;这个类的作用,就是加密密码的;

package com.imooc.admin.controller;

import org.springframework.security.crypto.bcrypt.BCrypt;


public class PWDTest {
    public static void main(String[] args) {

        
        String pwd = BCrypt.hashpw("admin", BCrypt.gensalt());
        System.out.println(pwd);

    }
}

说明:

(1)我们需要使用"Spring Security安全框架"中的【BCrypt.hashpw()工具类】(这个工具类是【org.springframework.security.crypto.bcrypt.BCrypt】包下的);为此,我们在【api】接口工程中,引入了【spring-cloud-starter-openfeign】;

          ● 在【spring-cloud-starter-openfeign】中,是有【org.springframework.security.crypto.bcrypt.BCrypt】包的;

(2)看注释;

(3)运行上面的代码,我们会得到一个字符串;

(4)至于,用户使用【admin,admin】登录的时候,密码是如何处理的,在本篇博客的后面会介绍;


二:开发管理员登录:Dao、Service部分;

这个【http://admin.imoocnews.com:8080/imooc-news/admin/login.html】就是后台系统管理员用户的登录页:

然后,我们接下来,就是开发管理员登录功能;

1.根据admin_user表,生成【实体类、mapper接口、mapper.xml】;

利用【15:第二章:架构后端项目:11:使用【mybatis-generator-core】依赖生成实体类、mapper接口、mapper.xml等逆向文件;】中,创建的【mybatis-generator-database】工程;去针对admin_user表,生成【实体类、mapper接口、mapper.xml】;

(1)创建【generatorConfig-admin.xml】,并创建对应的包;

(2)创建AdminGenerator工具类,去根据【generatorConfig-admin.xml】生成【实体类、mapper接口、mapper.xml】;

(3)然后,把根据admin_user表生成的【实体类、mapper接口、mapper.xml】,copy到【admin】管理服务对应的目录中去;

          ● 把pojo实体类,放到【model】中;

          ● 把mapper接口、mapper.xml,放到【admin】中;

2.在【imooc-news-dev-service-admin】管理服务中,创建管理员登录的Service部分;

(1)创建AdminUserService接口,定义【根据"管理员用户名",查询管理员用户】的方法;
package com.imooc.admin.service;

import com.imooc.pojo.AdminUser;


public interface AdminUserService {


    
    public AdminUser queryAdminByUsername(String username);
}

(2)创建AdminUserServiceImpl实现类,去实现【根据"管理员用户名",查询管理员用户】方法;
package com.imooc.admin.service.impl;

import com.imooc.admin.mapper.AdminUserMapper;
import com.imooc.admin.service.AdminUserService;
import com.imooc.pojo.AdminUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

@Service
public class AdminUserServiceImpl implements AdminUserService {

    @Autowired
    public AdminUserMapper adminUserMapper;

    
    @Override
    public AdminUser queryAdminByUsername(String username) {

        //1.利用tkmybatis的Example,自定义查询条件;
        // 1.1先创建一个查询实例,这个实例,是针对AdminUser作查询的;
        Example adminExample = new Example(AdminUser.class);
        // 1.2给上面的查询实例,增加查询条件;
        Example.Criteria criteria = adminExample.createCriteria();
        //第一个参数:AdminUser实体类中的username;第二个参数:queryAdminByUsername这个方法的username参数;
        criteria.andEqualTo("username", username);

        //2.利用创建好的查询条件,调用方法,去查数据库;
        AdminUser adminUser = adminUserMapper.selectOneByExample(adminExample);
        return adminUser;
    }
}

说明:

(1)需要注入AdminUserMapper接口对象; 

(2)在【26:第三章:开发通行证服务:9:【注册/登录】接口】中,我们就利用过tkmybatis的Example,自定义查询条件;然后,去查询数据库;如果有不明白的,可以去参考;

(3)注意:selectOneByExample()方法中,参数是Example adminExample,而不是criteria;别写错了;


三:开发管理员登录:Controller部分;

1.首先,在【api】接口工程中,定义AdminMngControllerApi接口,并定义【管理员登录】接口;

AdminMngControllerApi接口:

package com.imooc.api.controller.admin;

import com.imooc.bo.AdminLoginBO;
import com.imooc.bo.UpdateUserInfoBO;
import com.imooc.grace.result.GraceJSONResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

@Api(value = "管理员admin维护相关Controller",tags = {"管理员admin维护相关Controller"})
@RequestMapping("adminMng")  //设置路由,这个是需要前后端约定好的;
public interface AdminMngControllerApi {

    
    @ApiOperation(value = "管理员用户登录", notes = "管理员用户登录", httpMethod = "POST")
    @PostMapping("/adminLogin") //设置路由,这个是需要前后端约定好的;
    public GraceJSONResult adminLogin(@RequestBody @Valid AdminLoginBO adminLoginBO,
                                      BindingResult result,
                                      HttpServletRequest request,
                                      HttpServletResponse response);

}

说明:

(1)接口的url、参数类型、请求方式,都是前后端约定好的,别瞎写; 

(2)然后,我们在【model】模型工程中,创建了AdminLoginBO类,来承接用户在前端输入的用户名和密码;

          ● 自然,我们使用@Valid开启了参数校验;

          ● 同时,一旦校验失败,有错误信息后,我们就可以通过【BindingResult result】来获取对应的错误信息;所以,这儿在参数中,也引入了【BindingResult result】;

          ● 这儿的内容,在【30:第三章:开发通行证服务:13:开发【更改/完善用户信息,接口】;】等博客中也有介绍;如有需要,可以去参考;

2.然后,在【admin】管理服务工程中,定义AdminMngController类,去实现AdminMngControllerApi接口;实现【管理员登录】接口;

AdminMngController类:

package com.imooc.admin.controller;

import com.imooc.admin.service.AdminUserService;
import com.imooc.api.BaseController;
import com.imooc.api.controller.admin.AdminMngControllerApi;
import com.imooc.bo.AdminLoginBO;
import com.imooc.grace.result.GraceJSONResult;
import com.imooc.grace.result.ResponseStatusEnum;
import com.imooc.pojo.AdminUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.UUID;

@RestController
public class AdminMngController extends BaseController implements AdminMngControllerApi {

    @Autowired
    private AdminUserService adminUserService;

    
    @Override
    public GraceJSONResult adminLogin(AdminLoginBO adminLoginBO,
                                      BindingResult result,
                                      HttpServletRequest request,
                                      HttpServletResponse response) {

        //0.判断BindingResult中是否保存了验证失败的错误信息,如果有,说明前端的输入是有问题的(用户名或者密码,至少有一个没输入);
        // 那么,我们就获取这个错误信息,并构建一个GraceJSONResult统一返回对象,返回;
        if (result.hasErrors()) {
            Map map = getErrorsFromBindingResult(result);
            return GraceJSONResult.errorMap(map);
        }

        // 1.调用Service层的方法,根据用户名,尝试去数据库中查,看是否有这个用户;
        AdminUser adminUser = adminUserService.queryAdminByUsername(adminLoginBO.getUsername());
        // 2.判断adminUser是否为空;如果为空,则表示没有这个用户;
        if (adminUser == null) {
            //返回一个包含"管理员不存在或密码错误!"信息的,GraceJSONResult;
            return GraceJSONResult.errorCustom(ResponseStatusEnum.ADMIN_NOT_EXIT_ERROR);
        }

        
        boolean isPwdMatch = BCrypt.checkpw(adminLoginBO.getPassword(), adminUser.getPassword());
        //如果密码是OK的,直接返回OK的GraceJSONResult;
        if (isPwdMatch) {
            //首先,调用doLoginSettings方法,去把token信息保存到redis;token,id,name信息设置进cookie;
            doLoginSettings(adminUser,request,response);
            return GraceJSONResult.ok();
        } else {//如果密码不OK,
            //返回一个包含"管理员不存在或密码错误!"信息的,GraceJSONResult;
            return GraceJSONResult.errorCustom(ResponseStatusEnum.ADMIN_NOT_EXIT_ERROR);
        }
    }

    
    private void doLoginSettings(AdminUser adminUser,
                                 HttpServletRequest request,
                                 HttpServletResponse response) {
        // 1.将token存放到redis中;
        //用户会话,可以使用一个token;然后,token可以使用一个随机的uuid来做;
        String token = UUID.randomUUID().toString();
        //把该用户的token信息,保存在redis中;其key是【redis_admin_token:1001】这种;
        redisOperator.set(REDIS_ADMIN_TOKEN + ":" + adminUser.getId(), token);

        
        setCookie(request, response, "atoken", token, COOKIE_MONTH);
        setCookie(request, response, "aid", adminUser.getId(), COOKIE_MONTH);
        setCookie(request, response, "aname", adminUser.getAdminName(), COOKIE_MONTH);
    }
}

说明:

(1)首先,校验参数是否OK;如果不OK,就从BindingResult中提取出错误信息,直接返回对应的GraceJSONResult;

          ● 以前在【25:第三章:开发通行证服务:8:【注册/登录】接口:接收并校验“手机号和验证码”参数;】等博客中,有过介绍;如果有需要,可以去参考;

(2)向redis中保存token,设置cookie;

          ● 以前在【27:第三章:开发通行证服务:10:【注册/登录】接口:注册/登录OK后,把用户会话信息(uid,utoken)保存到redis和cookie中;】中,有过介绍;如果有需要,可以去参考;

(3)BCrypt.checkpw()方法,会自动核验密码是否OK;

(4)我们在BaseController中,定义了REDIS_ADMIN_TOKEN;


四:效果;

(1)先全局install一下整个项目;

(2)然后,启动前端项目;记得使用SwitchHost开启虚拟域名映射;

(3)启动【admin】管理服务的主启动类;

(4)访问【http://admin.imoocnews.com:8080/imooc-news/admin/login.html】后台系统管理员用户的登录页:

          ● 如果报了【There is no getter for property named ‘distinct‘ in ‘class tk.mybatis.mapper】错误,那么大概率是selectOneByExample()方法的参数,写错了;;;可以参考【There is no getter for property……】;

然后,如果输入密码admin的话,其OK了;

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1028390.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号