小程序登录(java后台)

基本顺序

        1.微信小程序的appId 
	2.微信小程序的secret
	3.ip在微信公众号里备案 
	4.添加业务域名会访问项目中的MP_verify_fQ6FF0R8GZHgK5Kl.txt (程序实现这个文件)
	5.wx.login()获取微信给的临时code 5分钟有效期	
	6.code2ession() 接口,使用code 和appid 和secret 换取用户的唯一标识openid和会话秘钥session_key

1.微信小程序的appId(去往小程序)

设置=====>开发设置 ====>appId

2.微信小程序的secret

设置=====>开发设置=====>secret

3.ip在公众号中备案

    基本设置====>IP白名单 可以设置多个ip 使用回车分隔

 

4.添加业务域名

点击公众号头像===>功能设置====>业务域名

设置自己的域名然后下载文件

这里使用代码替代 

域名设置  你的域名 xxx.com\mini  你的项目必须是启动 ,微信会去验证使用get方式

 

/**
 * @date: 2018/11/2 11:33
 * @author: YINLELE
 * @description:用于给微信验证用的
 */
@Controller
@RequestMapping("/mini")
public class MiniWxController {

    Logger logger = LoggerFactory.getLogger(MiniWxController.class);

    /*用于微信验证MVP文件*/
    @RequestMapping("MP_verify_{path}.txt")
    public void index(@PathVariable String path, HttpServletResponse response){
        try {
            PrintWriter writer = response.getWriter();
            writer.print(path);
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

 5.wx.login()获取微信给的临时code 5分钟有效期

     1.使用wx.login()获取微信用户的code(点击即可)

         这里面介绍了小程序登录以及加解密的原理和实现 

    2.这是获取session_key用于解密用户的加密信息的(点击即可)

 

小程序代码 wxml

<view class="login-container">

  <view class="login" wx:if="{{ !logged }}">

    <view class="app-info">

      <image class="app-logo" src="{{logo}}" />
      <text class="app-name">{{title}}</text>
    </view>

   <view class='form-item'>
      <input class='username' value='{{phone}}' bindinput='getPhone' placeholder='请输入手机号'>
      </input>
    </view>

    <button class="weui-btn" type="primary" open-type="getUserInfo" bindgetuserinfo="login">确认授权</button>
  </view>

  <view class="logged" wx:else>

    <image class="logged-icon" src="../../images/iconfont-weixin.png" />
    <view class="logged-text">近期你已经授权登陆过{{title}}</view>

    <view class="logged-text">自动登录中</view>
  </view>
</view>

小程序的js 我使用的是请求是封装好的 我又获取了用户的手机号 所以多个属性 一般解密用户信息在后台 解析

const app = getApp();
var httpUtil = require("../../../utils/httpUtil.js");
var api = require("../../../config/api.js");
Page({
  data: {
    phone: "",
    fail: "网络繁忙"
  },
  onLoad: function() {

  },
  getPhone: function(e) {
    this.setData({
      phone: e.detail.value
    });
    console.log(this.data.phone);
  },
  login: function(e) {
    var that = this;
    wx.login({
      success: function(r) {
        var code = r.code; //登录凭证 
        console.log(code)
        if (code) {
          //2、调用获取用户信息接口  
          wx.getUserInfo({
            success: function(res) {
              console.log(JSON.stringify("获取的用户信息:===>" + that.data.phone));
              var data = {
                "code": r.code,//用户code
                "encryptedData": res.encryptedData,//用户信息不过被加密 需要使用session_key解密
                "iv": res.iv,//参与解密用户信息的向量
                "phone": that.data.phone//手机号
              };
              //3.请求自己的服务器,解密用户信息 获取unionId等加密信息  
              httpUtil.http_post(api.LoginCodeUrl, data).then((res) => {
                console.log("用户信息====>" + JSON.stringify(res));
                if (res.status == 80200) {
                  app.globalData.userInfo = res.data;
                  wx.setStorageSync('userInfo', res.data);
                  wx.switchTab({
                    url: '/pages/index/index',
                  })
                } else {
                  wx.showToast({
                    title: that.data.fail,
                    icon: "loading",
                    duration: 2000
                  })
                }
              });
            },
            fail: function() {
              console.log('获取用户信息失败')
            }
          })

        } else {
          console.log('获取用户登录态失败!' + r.errMsg)
        }
      },
      fail: function() {
        console.log('登陆失败')
      }
    })
  }
})

 小程序的wxss

.login-container {
  height: 100%;
  padding: 10px 30px;
  background: #fff;
}

.app-info {
  position:relative;
  padding:20px;
  text-align:center;
}

.app-info:after {
    content: " ";
    position: absolute;
    left: 0;
    bottom: 0;
    right: 0;
    height: 1px;
    border-bottom: 1px solid #E5E5E5;
    color: #E5E5E5;
    -webkit-transform-origin: 0 100%;
    transform-origin: 0 100%;
    -webkit-transform: scaleY(0.5);
    transform: scaleY(0.5);
}

.app-info .app-logo {
display: block;
width: 64px;
height: 64px;
margin: 10px auto;
border-radius: 4px;
}

.app-info .app-name {
font-weight: bold;
font-size: 18px;
color: #000;
}

.alert {
margin: 20px 0 30px;
}

.alert .alert-title {
  font-weight: 400;
  font-size: 16px;
  color: #000;
  margin-bottom: 10px;
}

.alert-desc {
  display: block;
  list-style: disc inside none;
}

.alert .alert-text {
  display: list-item;
  text-align: -webkit-match-parent;
  font-size: 14px;
  color: #999;
}

.logged {
  margin-top: 100px;
}

.logged .logged-icon {
  display: block;
  width: 64px;
  height: 64px;
  margin: 20px auto;
}

.logged .logged-text {  
  font-size: 14px;
  color: #000;
  text-align: center;
  margin: 10px 0;
}

.form-item{
    position: relative;
    background: #fff;
    height: 96rpx;
    border-bottom: 1px solid #d9d9d9;
}

.form-item .username, .form-item .password, .form-item .code{
    position: absolute;
    top: 26rpx;
    left: 0;
    display: block;
    width: 100%;
    height: 44rpx;
    background: #fff;
    color: #333;
    font-size: 30rpx;
}

6.后台获取小程序传过来的值进行解密

import java.util.Map;

/**
 * @date: 2018/10/26 15:51
 * @author: YINLELE
 * @description: 用于小程序登录
 */
@RestController
@RequestMapping("/mini/login")
public class MiniLoginController extends BaseController {
    Logger logger =LoggerFactory.getLogger(MiniLoginController.class);

    @Autowired
    private UserService userService;

    @ResponseBody
    @PostMapping("/wxUserInfo")
    public ResponseBean wxLoginToken(@RequestBody WxEncryption wxEncryption) throws Exception {
        logger.info("wxUserInfo={}",wxEncryption);
        //准备url,获取用户的session_key和openId信息
        String urlSM=WxSPConfig.CODE2_SESSION_URL.replace("APPID",WxSPConfig.APP_ID_SMALL_PROGRAM).replace("SECRET",WxSPConfig.SECRET_SMALL_PROGRAM).replace("JSCODE",wxEncryption.getCode());
        logger.info("urlSM={}",urlSM);
        //请求微信接口获取信息
        RestTemplate template = new RestTemplate();
        ResponseEntity<String> responseSM = template.getForEntity(urlSM, String.class);
        logger.info("responseSM={}",responseSM);
        //转换成map集合
        String bodySM = responseSM.getBody();
        WxUserInfoVO wxUserInfoVO = FastJsonUtil.getObject(bodySM, WxUserInfoVO.class);
        //获取解密后的数据
        String jsonData = AesCbcUtil.decrypt(wxEncryption.getEncryptedData(), wxUserInfoVO.getSession_key(),wxEncryption.getIv(), "UTF-8");
        logger.info("wxUserInfoVO={}",wxUserInfoVO);
        WxUserInfoVO userInfoVO = FastJsonUtil.getObject(jsonData, WxUserInfoVO.class);
        userInfoVO.setSession_key(wxUserInfoVO.getSession_key());
        userInfoVO.setWxUserInfo(jsonData);
        //根据openid查询
        UserEntity userEntity=userService.findByOpenId(userInfoVO.getOpenId());
        if(null==userEntity){
            userInfoVO = userService.saveUserByWx(userInfoVO, wxEncryption);
        }else{
            userInfoVO = userService.updateUserByWx(userInfoVO, wxEncryption);
        }
        userInfoVO.setWxUserInfo(null);
        userInfoVO.setSession_key(null);
        return ResponseUtil.success(userInfoVO);
    }

}

使用的实体类

package com.aui.stock.controller.mini.vo;

/**
 * @date: 2018/11/6 23:46
 * @author: YINLELE
 * @description: 用户存储用户信息
 */
public class WxUserInfoVO {

    /*微信用户在系统的的唯一ID*/
    private Long sn;

    /*用户唯一的标识*/
    private String openId;

    /*微信用户的昵称*/
    private String nickName;

    /*微信用户的性别*/
    private String  gender;

    /*微信用户的城市*/
    private String city;

    /*微信用户的省*/
    private String province;

    /*微信用户的国家*/
    private String country;

    /*微信用户的头像*/
    private String avatarUrl;

    /*用户手机号*/
    private String phone;

    /*用户的语言*/
    private String language;

    /*用户秘钥*/
    private String session_key;

    /*用户信息json*/
    private String wxUserInfo;

    public String getWxUserInfo() {
        return wxUserInfo;
    }

    public void setWxUserInfo(String wxUserInfo) {
        this.wxUserInfo = wxUserInfo;
    }

    public String getOpenId() {
        return openId;
    }

    public void setOpenId(String openId) {
        this.openId = openId;
    }

    public Long getSn() {
        return sn;
    }

    public void setSn(Long sn) {
        this.sn = sn;
    }

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getAvatarUrl() {
        return avatarUrl;
    }

    public void setAvatarUrl(String avatarUrl) {
        this.avatarUrl = avatarUrl;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getLanguage() {
        return language;
    }

    public void setLanguage(String language) {
        this.language = language;
    }

    public String getSession_key() {
        return session_key;
    }

    public void setSession_key(String session_key) {
        this.session_key = session_key;
    }
    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("WxUserInfoVO{");
        sb.append("sn=").append(sn);
        sb.append(", nickName='").append(nickName).append('\'');
        sb.append(", gender='").append(gender).append('\'');
        sb.append(", city='").append(city).append('\'');
        sb.append(", province='").append(province).append('\'');
        sb.append(", country='").append(country).append('\'');
        sb.append(", avatarUrl='").append(avatarUrl).append('\'');
        sb.append(", phone='").append(phone).append('\'');
        sb.append(", language='").append(language).append('\'');
        sb.append(", session_key='").append(session_key).append('\'');
        sb.append('}');
        return sb.toString();
    }
}

 

package com.aui.stock.controller.mini.to;

/**
 * @date: 2018/11/6 22:27
 * @author: YINLELE
 * @description: 用于接受微信登录的参数
 */
public class WxEncryption {

    /*用户登录的code 有效期5分钟*/
    private String code;

    /*用户的加密信息*/
    private String encryptedData;

    /*加密算法的初始向量*/
    private String iv;

    /*用户手机号*/
    private String phone;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getEncryptedData() {
        return encryptedData;
    }

    public void setEncryptedData(String encryptedData) {
        this.encryptedData = encryptedData;
    }

    public String getIv() {
        return iv;
    }

    public void setIv(String iv) {
        this.iv = iv;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("WxEncryption{");
        sb.append("code='").append(code).append('\'');
        sb.append(", encryptedData='").append(encryptedData).append('\'');
        sb.append(", iv='").append(iv).append('\'');
        sb.append('}');
        return sb.toString();
    }
}

 解密的工具类

package com.aui.stock.util;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidParameterSpecException;
import java.util.Arrays;

/**
 * @date: 2018/11/6 22:49
 * @author: YINLELE
 * @description:
 *   AES-128-CBC 加密方式
 *   注:
 *   AES-128-CBC可以自己定义“密钥”和“偏移量“。
 *   AES-128是jdk自动生成的“密钥”。
 */
public class AesCbcUtil {

    static {
        //BouncyCastle是一个开源的加解密解决方案,主页在http://www.bouncycastle.org/
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * AES解密
     *
     * @param data           //密文,被加密的数据
     * @param key            //秘钥
     * @param iv             //偏移量
     * @param encodingFormat //解密后的结果需要进行的编码
     * @return
     * @throws Exception
     */
    public static String decrypt(String data, String key, String iv, String encodingFormat) throws Exception {

        //被加密的数据
        byte[] dataByte = Base64.decodeBase64(data);
        //加密秘钥
        byte[] keyByte = Base64.decodeBase64(key);
        //偏移量
        byte[] ivByte = Base64.decodeBase64(iv);


        try {
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, encodingFormat);
                return result;
            }
            return null;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidParameterSpecException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

}

解密所需要的maven坐标

     <!--用于小程序解密-->
        <dependency>
            <groupId>org.codehaus.xfire</groupId>
            <artifactId>xfire-core</artifactId>
            <version>1.2.6</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.60</version>
        </dependency>
        <!--小程序解密-->

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
小程序一般是指微信小程序,而Java后台源码则是指以Java语言编写的后台服务代码。 微信小程序是一种基于微信平台的轻量级应用,可在微信内直接使用,为用户提供各种功能和服务。小程序通常包含前端和后台两部分,前端部分主要负责用户界面的展示和交互,后台部分则负责处理逻辑、存储数据和调用相应的API接口。 Java后台源码通常用于构建和部署后台服务,通过Java语言编写的代码实现与数据库的交互、数据的处理和业务逻辑的实现。后台源码一般包括各种业务逻辑的类、接口和数据库连接设置等。 如果要将Java后台源码与小程序结合使用,首先需要确保小程序具备调用后台服务的能力。可以在小程序中使用微信提供的API,通过HTTP请求或WebSocket与后台进行通信。同时,需要在Java后台源码中实现相应的接口,处理前端请求并返回数据。 在设计小程序Java后台源码之间的通讯接口时,可以遵循RESTful架构风格,通过标准的HTTP请求方式进行交互。前端通过发送请求,后台对请求进行解析,并根据请求的内容进行相应的处理,最后将处理结果以JSON等格式返回给前端。 当然,在实际实现中还需要考虑到安全性、性能优化、数据库连接池等方面的问题。同时,为了保证代码质量和可维护性,需要采用合理的设计模式和架构思想,编写具有良好结构和可扩展性的代码。 总之,将小程序Java后台源码结合使用,能够实现多种功能和服务,如用户登录验证、数据的增删改查、信息推送等。这样的组合能够满足用户对功能和性能的要求,并提供更好的用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值