3.(UAI-APP创建移动端)疫情下的在线办公签到系统


一、注册新用户的业务要点说明

管理者在创建新员工记录的时候,并不知道新员工的微信账号,所以没办法完成绑定,需要新员工自己完成绑定。于是新员工在Emos小程序注册页面,填写激活码之后,Emos小程序获取新员工的微信账号信息,提交给Emos后台系统,后端系统把微信账号与新员工账号关联在一起,然后保存到MySQL数据库。
其实把微信账号与小程序关联在一起很简单,就是把微信基本信息(昵称、头像)和 OpenId ,存储到员工记录上面。因为每个微信账号的 OpenId 在当前的小程序上面都是 唯一的 ,只要MySQL记录下每名员工微信账号的 OpenId ,那么就实现了员工记录与微信账号的绑定。员工登陆Emos小程序的时候,后端系统会拿着这个微信帐户的 OpenId 与数据库中的 OpenId 比对。如果用户表不存在这个 OpenId ,说明该微信帐户没有绑定员工账号,所以Emos拒绝用户登陆。如果用户表存在这个 OpenId ,那么就判定用户登陆成功。

二、如何获取微信账号的OpenId字符串

首先可以从微信APP上获取用户临时授权字符串(Code),然后把这个字符串传递给后端java系统,让系统拿着AppId,密匙,和Code,提交给微信平台换取OpenId

String url = "https://api.weixin.qq.com/sns/jscode2session"
HashMap map = new HashMap();
map.put("appid",appId);
map.put("secret",appSecret);
map.put("js_code",code);
map.put("grant_type","authorization_code");
String response = HttpUtil.post(url.map);
JSONObject json = JSONUtil.parseObj(response);
String openId = json.getSrt("openid");

1.获取临时授权和微信基本信息

uni.login({
 provider: 'weixin',
 success: function(resp){
 console.log(resp.code);
}
})
uni.login({
 provider: 'weixin',
 success: function(resp){
 let code = resp.code;
 uni.getUserInfo({
   provider: 'weixin',
   success: function(resp){
   let nickname = reap.userInfo.nickname;
   let avatarUrl = resp.userInfo.avataUrl;
} 
})
}
})

三、实现注册超级管理员功能(持久层)

1.判断系统是否已经绑定超级管理员

Emos系统中只可以绑定唯一的超级管理员账号,当用户输入000000这个激活码时,后端必须要判断是否可以绑定超级管理员,通过SQL语句查询用户表是否存在超级管理员账户,只要查询root字段值为1的记录数量就可以

<select id="haveRootUser" resultType="boolean">
  SELECT if(COUNT(*),TRUE,FALSE) FROM tb_user WHERE root=1;
</select>

2.编写保存用户记录的代码

假设业务层判断用户可以注册为超级管理员,把用户数据保存在用户表

 <insert id="insert" parameterType="HashMap">
       INSERT INTO tb_user
         SET
         <if test="openId!=null">
        open_id = #{openId},
         </if>
         <if test="nickname!=null">
         nickname = #{nickname},
         </if>
         <if test="photo!=null">
         photo = #{photo},
         </if>
         <if test="name!=null">
         name = #{name},
         </if>
         <if test="sex!=null">
         sex = #{sex},
         </if>
       <if test="tel!=null">
         tel = #{tel},
         </if>
         <if test="email!=null">
         email=#{email},
         </if>
         <if test="hiredate!=null">
        hiredate = #{hiredate},
         </if>
         role = #{role},
        root = #{root},
         <if test="deptName!=null">
         dept_id = ( SELECT id FROM tb_dept WHERE dept_name = #{deptName} ),
         </if>
       status = #{status},
         create_time = #{createTime}
   </insert>

3.编写查询用户ID代码

如果在员工表中插入新纪录,由于主键是自动生成的,所以我们并不知道新纪录的主键值是多少。于是我们要编写代码,根据OpenId查询用户ID

<select id="searchIdByOpenId" resultType="Integer" parameterType="String">
   SELCET id FROM tb_user WHERE open_id = #{openId} AND status=1;
<select>

四、实现注册超级管理员功能(业务层)

1.获取OpenId

获取微信用户的OpenId,需要后端程序向微信平台发出请求,并上传若干参数,最终才能得到。

@Service
@Slf4j
@Scope("prototype")
public class UserServiceImpl implements UserService{
      @Value("${wx.app-id}")
      private String appId;
      @Value("${wx.app-secret}")
      private String appSecret;
      @Autowired
      private TbUserDao userDao;
      private String getOpenId(String code){
      String url = "https://api.weixin.qq.com/sns/jscode2session";
      HashMap map = new HashMap();
      map.put("appId",appId);
      map.put("secret",appSecret);
      map.put("js_code",code);
      map.put("grant_type","authorization_code");
      String response = HttpUtil.post(url,map);
      JSONObject json = JSONUtil.parseObj(response);
      String openId = json.getStr("openid");
      if(openId == null || openId.length() == 0){
       throw new RuntimeException("临时登录凭证错误");
}
      return openId;
}
}

2.注册新用户

 @Override
 public int registerUser(String regisetrCode,String code,String nickname,String photo){
    if(registerCode.equals("000000")){
       boolean bool = userDao.haveRootUser();
       if(!bool){
       String openId = getOpenId(code);
       HashMap param = new HashMap();
       param.put("openId",openId);
       param.put("nickname",nickname);
       param.put("photo",photo);
       param.put("role","[0]");
       param.put("status",1);
       param.put("createTime",new Date());
       param.put("root",true);
       userDao.insert(param);
       int id = userDao.searchIdByOpenId(openId);
       return id; 
}else{
   throw new EmosException("无法绑定超级管理员账户");
}
}
//此处还有其他判断
else{
   return 0;
  }
}

五、掌握RABC权限模型

1.RABC权限模型

RBAC的基本思想是对系统操作的权限不是直接授予具体的用户,而是在用户集合和权限集合间建立一个角,每一种角色对应一种相应的权限,这样做的好处在于不用在每次创建用户时都进行分配权限的操作,只要分配相应的角色即可,而角色的权限变更比用户的权限变更要少得多,这样将简化用户得权限管理。
在角色表(tb_role)中设置得permissions字段,类型是JSON格式的
在用户表(tb_user)上设置role字段,类型也为JSON的

2.前后端权限验证

关于权限验证的工作,前端要做,后端也要做。后端的权限验证还好说,Shiro框架可以做这个事情。但是移动端没有权限验证框架,所以需要我们自己封装函数来验证权限。每个页面在渲染的时候,先判断用户拥有什么权限,然后根据权限控制渲染的内容。比如说普通员工没有添加新员工的权限,所以界面上就不能出现添加按钮。
移动端做权限判断的前提是必须有当前用户的 权限列表 ,这个权限列表是用户 登陆成功 或者 注册成功 ,后端Java项目返回给移动端的,移动端保存到本地 Storage 里面。

3.如何查询用户的权限列表?

<select id="searchUserPermission" parameterType="int" resultType="String">
 SELECT p.permission_name
 FROM tb_user u
 JOIN tb_role ON JSON_CONTAINS(u.role,CAST(r.id AS CHAR))
 JOIN tb_permission p ON JSON_CONTAINS(r.permission,CAST(p.id AS CHAR))
 WHERE u.id = #{userId} AND u.status = 1;
</select>

六、实现注册超级管理员功能(Web层)

接收移动端提交的注册请求,我们需要用表单类来封装数据,所以创建 RegisterForm.java 类。

1.创建表单

@Date
@ApiModel
public class RegisterForm{
   @NotBlank(message = "注册码不能为空")
   @Pattern(regexp = "^[0-9]{6}$",message = "注册码必须是6位数字")
   private String registerCode;
   @NotBlank(message = "微信临时授权不能为空")
   private String code;
   @NotBlank(message = "呢称不能为空")
   private String nickname;
   @NotBlank(message = "头像不能为空")
   private String photo;
}

2.创建Controller类

@RestController
@RequestMapping("/user")
@Api("用户模块Web接口")
public class UserController{
   @Autowired
   private UserService userService;
   @Autowired
   private JwtUtil jwtUtil;
   @Autowired
   private RedisTemplate redisTemplate;
   @Value("${emos.jwt.cache-expire}")
   private int cacheExpire;
   @PostMapping("/register")
   @ApiModel("注册用户")
   public R register(@Valid @RequestBody RegisterForm form){
     int id = userService.registerUser(form.getRegisterCode(),form.getCode(),form. getNickname(),form.getPhoto);
     String token = jwtUtil.createToken(id);
     Set<String> permsSet = userService.searchUserPermission(id);
     saveCacheToken(token,id);
     return R.ok("用户注册成功").put("token",token).put("permsSet",permsSet);
}
public void saveCacheToken(String token, int userId){
  redisTemplate.opsForValue().set(token,userId+"",cacheExpire,TimeUnit.DAYS);
}
}

六、定义全局路径和封装Ajax(移动端)

移动端发出请求,首先要填写好URL地址。为了在移动端项目上集中管理URL路径,我们可以在 main.js 文件中用全局变量的语法,定义全局的URL地址,这样更加便于维护。

let baseUrl = "http://192.168.99.216:8080/emos-wx-api"
Vue.prototype.url={
  register: baseUrl+"/user/register",
}

移动端通过Ajax向服务端提交请求,然后接收到的响应分若干种情况:如果移动端每次发出Ajax,都要做这么多的判断,我们的重复性劳动太多了。所以尽可能的把
Ajax封装起来,减少重复性的劳动

Vue.prototype.ajax=function(url,methon,data,fun){
     uni.request({
     "url":url,
     "method":method,
     "header":{
      token:uni.getStorageSync('token')
},
     "data":data,
     success: function(resp){
      if(resp.statusCode == 401){
      uni.redirecTo({
      url:'../login/login'
});
}else if(resp.statusCode == 200 && resp.data.code == 200){
   let data == resp.data
   if(data.hasOwnProperty("token")){
    let token = data.token
    uni.setStorageSync("token",token)
}
 fun(resp)
}else{
   uni.showToast({
   icon:'none',
   title:reps.data
});
}
}
});
}

1.前端验证功能

let  that=this;
if(that.registerCode == null || that.registerCode.length == 0){
     uni.showToast({
   icon:'none',
   title:'邀请码不能为空'
});
return 
}
else if(/^[0-9]{6}$/.test(that.registerCode) == false) {
   uni.showToast({
   icon:'none',
   title:'邀请码必须为6位数字'
});
}

2.提交Ajax请求

   let data={
   code:code,
   nickname:nickname,
   photo:photo,
   registerCode:that.registerCode
}
  that.ajax(that.url.register,'POST',data,function(resp)){
  let permission = resp.data.permission;
  uni.setStorageSync('permission',permission);
  //跳转到index页面
}

七、实现用户登录功能

1.如何判定登录

用户表(tb_user)中没有密码字段,无法根据username和password判断用户是否可以登录。在EMOS系统中用户拿着微信登录小程序,在用户表中只有openId,nickname和photo跟微信账号相关。
用户在EMOS系统登录,然后小程序把临时字符串给后端系统,后端拿着临时字符串换取openid,然后查询用户表中是否存在openid,如果存在,表示用户已经注册,可以登录
Dao

<select id="searchIdByOpenId" parameterType="String" resultType="Integer">
  SELECT id FROM tb_user WHERE open_id=#{openId} AND status = 1
<select>

Service

public Integer login(String code){
    String openId = getOpenId(code);
    Integer id = userDao.searchIdByOpenId(openId);
    if(id == null){
     throw new EmosException("账户不存在");
}
//从消息队列中接受消息,转移到消息表
return id;
}

Web
封装客户提交的数据

@ApiModel
@Data
public class LoginForm{
  @NotBlank(message = "临时授权不能为空")
  private String code;
}
@PostMapping("/login")
@ApiOperation("登录系统")
public R login(@Valid @RequestBody LoginForm form){
        int id = userService.login(form.getCode());
        String token = jwtUtil.createToken(id);
        Set<String> permission = userService.searchUserPermission(id);
        saveCacheToken(token,id);
        return R.ok("登录成功").put("token",token).put("permission",permission);
}

判断用户登录成功后,向客户端返回权限列表和token令牌

2.移动端

Vue.prototype.url={
login:baseUrl+"/user/login"
}
let that = this;
uni.login({
   provider:'weixin',
   success:function(resp){
   let code = resp.code;
   that.ajax(that.url.login,'POST',{"code":code},function(resp)){
     let permission = resp.data.permission;
     uni.setStroageSync('permission',permission);
     //跳转到登录页面
})
},
fail:function(e){
   console.log(e)
   uni.showToast({
   icon:"none",
   title:"执行异常"
})
}
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值