精华内容
下载资源
问答
  • 抖音用户信息爬取案例

    万次阅读 多人点赞 2019-06-17 17:27:12
    抓包。抓到了一个share_url 我访问过去看了下, https://www.iesdouyin.com/share/user/102064772608 有数据的。那就拿数据。 然后发现它的数字做了字符集映射。 搞他。 下载.ttf的文件,s3a.bytecdn....


    注意:

    之前的代码已经失效,暂时先不删除。

    可根据目录直接到页面最底部查看最新采集方法。


    2019年6月17更新(已失效)

    抓包。抓到了一个share_url
    在这里插入图片描述
    在这里插入图片描述
    我访问过去看了下,https://www.iesdouyin.com/share/user/102064772608?
    在这里插入图片描述
    有数据的。那就拿数据。

    然后发现它的数字做了字符集映射。
    在这里插入图片描述
    搞他。

    下载.ttf的文件,s3a.bytecdn.cn/ies/resource/falcon/douyin_falcon/static/font/iconfont_da2e2ef.ttf,这个便用font creator软件打开,看到这个图片我们就明白了字体与数字的关系
    在这里插入图片描述
    既然我们看到num_对应数字1,num_8对应数字7,那这个num_8们怎么得到,与‘ ’有啥关系?

    2.这个时候,需要大家安装pip install fontTools,使用fontTool打开ttf文件转化成xml文件,

    采用下面代码

    from fontTools.ttLib import TTFont
    font_1 = TTFont('douyin.ttf')
    font_1.saveXML('font_1.xml')
    

    我们看到了font_1.xml,

    在这里插入图片描述
    这就能看出来了。

    import re
    def getDouyinNum(douIDNumCode):
        mapCode2Font = {
            '0xe602': 'num_',
            '0xe603': 'num_1',
            '0xe604': 'num_2',
            '0xe605': 'num_3',
            '0xe606': 'num_4',
            '0xe607': 'num_5',
            '0xe608': 'num_6',
            '0xe609': 'num_7',
            '0xe60a': 'num_8',
            '0xe60b': 'num_9',
            '0xe60c': 'num_4',
            '0xe60d': 'num_1',
            '0xe60e': 'num_',
            '0xe60f': 'num_5',
            '0xe610': 'num_3',
            '0xe611': 'num_2',
            '0xe612': 'num_6',
            '0xe613': 'num_8',
            '0xe614': 'num_9',
            '0xe615': 'num_7',
            '0xe616': 'num_1',
            '0xe617': 'num_3',
            '0xe618': 'num_',
            '0xe619': 'num_4',
            '0xe61a': 'num_2',
            '0xe61b': 'num_5',
            '0xe61c': 'num_8',
            '0xe61d': 'num_9',
            '0xe61e': 'num_7',
            '0xe61f': 'num_6',
        }
        mapFont2Num = {
            'num_': 1,
            'num_1': 0,
            'num_2': 3,
            'num_3': 2,
            'num_4': 4,
            'num_5': 5,
            'num_6': 6,
            'num_7': 9,
            'num_8': 7,
            'num_9': 8,
        }
        douIDNum = ''
        map1 = {}
        if douIDNumCode == '':
            return ''
        for i in douIDNumCode:
            j = i.replace(' &#', '0').replace('; ', '')
            map1[j] = str(mapFont2Num[mapCode2Font[j]])
        return map1
    
    def req(share_id):
        url2= 'https://www.iesdouyin.com/share/user/{}'.format(share_id)
        headers ={
            "User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) "
                         "AppleWebKit/537.36 (KHTML, like Gecko) "
                         "Chrome/74.0.3729.169 Safari/537.36"
                }
        res=requests.get(url2,verify=False,headers=headers)
        return res
    
    def parse(res):
        description_header = re.findall('抖音ID:     (.*?)   </p>',res.text,re.S)
        description_back = re.findall('<i class="icon iconfont ">(.*?)</i>',res.text,re.S)
        mapDict = getDouyinNum(douIDNumCode=description_back)
        res = description_header[0]
        for i,j in mapDict.items():
            res = res.replace('<i class="icon iconfont "> &#'+i[1:]+'; </i>',j)
        print(res)
    
    
    if __name__ == '__main__':
        res =  req(102064772608)
        parse(res)
    

    在这里插入图片描述
    在这里插入图片描述

    2019年8月更新(已失效)

    检测到最近很多同学都在看这篇文章,我就重新写了一遍,思路还是跟上面一样,这次获取的是所有的用户信息。

    在这里插入图片描述
    如果有用,还请点赞或者留言

    import re
    import requests
    from lxml import etree
    '''
                             抖音用户基本信息 -> 请求share来获取数据 
    '''
    
    def handle_decode(input_data):
        # 匹配icon font
        regex_list = [
            {'name': [' &#xe603; ', ' &#xe60d; ', ' &#xe616; '], 'value': 0},
            {'name': [' &#xe602; ', ' &#xe60e; ', ' &#xe618; '], 'value': 1},
            {'name': [' &#xe605; ', ' &#xe610; ', ' &#xe617; '], 'value': 2},
            {'name': [' &#xe604; ', ' &#xe611; ', ' &#xe61a; '], 'value': 3},
            {'name': [' &#xe606; ', ' &#xe60c; ', ' &#xe619; '], 'value': 4},
            {'name': [' &#xe607; ', ' &#xe60f; ', ' &#xe61b; '], 'value': 5},
            {'name': [' &#xe608; ', ' &#xe612; ', ' &#xe61f; '], 'value': 6},
            {'name': [' &#xe60a; ', ' &#xe613; ', ' &#xe61c; '], 'value': 7},
            {'name': [' &#xe60b; ', ' &#xe614; ', ' &#xe61d; '], 'value': 8},
            {'name': [' &#xe609; ', ' &#xe615; ', ' &#xe61e; '], 'value': 9},
        ]
    
        for i1 in regex_list:
            for i2 in i1['name']:
                input_data = re.sub(i2, str(i1['value']), input_data)       # 把正确value替换到自定义字体上
    
        html = etree.HTML(input_data)
        douyin_info = {}
        # 获取昵称
        douyin_info['nick_name'] = html.xpath("//div[@class='personal-card']/div[@class='info1']//p[@class='nickname']/text()")[0]
        # 获取抖音ID
        douyin_id = html.xpath("//div[@class='personal-card']/div[@class='info1']/p[@class='shortid']//text()")
        douyin_info['douyin_id'] = ''.join(douyin_id).replace('抖音ID:', '').replace(' ', '')
    
        # 职位类型
        try:
            douyin_info['job'] = html.xpath("//div[@class='personal-card']/div[@class='info2']/div[@class='verify-info']/span[@class='info']/text()")[0].strip()
        except:
            pass
        # 描述
        douyin_info['describe'] = html.xpath("//div[@class='personal-card']/div[@class='info2']/p[@class='signature']/text()")[0].replace('\n', ',')
        # 关注
        douyin_info['follow_count'] = html.xpath("//div[@class='personal-card']/div[@class='info2']/p[@class='follow-info']//span[@class='focus block']//i[@class='icon iconfont follow-num']/text()")[0].strip()
        # 粉丝
        fans_value = ''.join(html.xpath("//div[@class='personal-card']/div[@class='info2']/p[@class='follow-info']//span[@class='follower block']//i[@class='icon iconfont follow-num']/text()"))
        unit = html.xpath("//div[@class='personal-card']/div[@class='info2']/p[@class='follow-info']//span[@class='follower block']/span[@class='num']/text()")
        if unit[-1].strip() == 'w':
            douyin_info['fans'] = str(float(fans_value) / 10) + 'w'
        else:
            douyin_info['fans'] = fans_value
        # 点赞
        like = ''.join(html.xpath("//div[@class='personal-card']/div[@class='info2']/p[@class='follow-info']//span[@class='liked-num block']//i[@class='icon iconfont follow-num']/text()"))
        unit = html.xpath("//div[@class='personal-card']/div[@class='info2']/p[@class='follow-info']//span[@class='liked-num block']/span[@class='num']/text()")
        if unit[-1].strip() == 'w':
            douyin_info['like'] = str(float(like) / 10) + 'w'
        else:
            douyin_info['like'] = like
    
        return douyin_info
    
    
    def handle_douyin_info(url):
        header = {
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36'
        }
        response = requests.get(url=url, headers=header)
        return handle_decode(response.text)
    
    if __name__ == '__main__':
        url = 'https://www.amemv.com/share/user/102064772608'     # 抖音新分享页的链接
        #url = 'https://www.iesdouyin.com/share/user/102064772608'
        print(handle_douyin_info(url))
    

    2020年6月24更新

    抖音更新了分享页面,现在分为了两版:

    在这里插入图片描述

    2021/03/03更新(可用)

    用户信息还可以使用上面的接口。

    分享页面用户信息接口https://www.iesdouyin.com/web/api/v2/user/info/

    分享页面用户视频数据https://blog.csdn.net/weixin_43582101/article/details/114291365


    2021/06/21 网页版(可用)

    抖音web页面的官网开放了。

    抖音网页版signature逻辑分析和生成源码https://blog.csdn.net/weixin_43582101/article/details/118084709

    网页版可采集用户列表、用户详情、用户视频、视频评论等数据


    ps:

    《爬虫案例合集》:以优质爬虫案例为主,解决疑难爬虫问题

    《签名逆向合集》:各类签名逆向分析,持续更新,值得订阅

    在这里插入图片描述

    展开全文
  • 微信小程序授权 获取用户信息

    万次阅读 多人点赞 2018-05-30 18:25:37
    获取用户信息(用户信息、获取unionId、openId)请移步到这里 用户打开小程序时,直接弹框获取用户信息授权,可能会立马懵圈: 你是谁? 我在哪里? 我为什么要同意?…… 相当一部分用户下意识会拒绝...

    小程序在18年4月25日做了一次更新,不再支持直接弹出授权信息框

    具体代码请看这里:  >>       获取用户信息(用户信息、获取unionId、openId)请移步到这里

     

    用户打开小程序时,直接弹框获取用户信息授权,可能会立马懵圈:

     

    你是谁?

    我在哪里?

    我为什么要同意?……

     

     

    相当一部分用户下意识会拒绝授权——这样不合理的登录流程既造成了用户的困扰,还流失了用户。

     

    用户通过小程序可以快速获取服务,因此在访问小程序的第一个页面非常重要

     

    小程序和小游戏内的用户登录,我们推荐使用以下两种方式获取用户信息:

     

    ▷ 按钮组件的登录方式,用户主动点击按钮可以拉起用户授权弹框,获取用户头像、昵称等信息;

     

    ▷ 在不获取用户信息的情况下,可展示用户头像昵称

     

    也提醒大家:

     

    用户在没有任何操作的情况直接弹出授权的登录方式将逐渐不再支持,受影响的有 wx.getUserInfo 接口,以及 wx.authorize 接口传入 scope="scope.userInfo" 的情况。

     

    为什么平台要做接口调整?

     

    小程序提供wx.login 和 wx.getUserInfo 接口,用于获取用户的 openID 和基本信息

     

    推出这两个接口的初衷是希望:

     

    当用户使用小程序时,只有访问到真正需要登录的页面,才需要授权并登录。

     

    对于一个互联网产品而言,第一个页面决定了用户对这个产品的认知,用户会选择是否继续使用这个产品。

     

    一个优秀的互联网产品,能够给用户留下一个好的第一印象,用户可以快速了解你的产品,接收到你想要传递的服务信息,从而产生相应的操作行为。

     

    一个优秀的小程序会吸引用户在小程序里进行探索,完成你期望他们去做的事,比如会员注册、商品购买等。

     

    试想一下如果一个品牌的商品官网,一进入要求用户登录才能查看产品信息是什么感觉呢?

     

    因此良好的用户登录体验非常重要。

     

     

    如何设计登录流程?

     

    用户打开小程序时,看第一眼的时候,开发者需要专注以下两个目标:

     

    ▷ 精准快速地传达产品理念,开发者要让用户能够快速了解自己的产品和服务;

     

    ▷ 将用户流量进行转化,让用户能方便操作或者交易。

     

    一般而言,用户打开小程序后看到的第一个页面,先不要直接弹出授权框,第一个页面可以包含以下内容:

     

    ▷ 展示你的小程序功能(如产品、服务、活动等) ,让用户清晰地知道小程序是做什么用的,这些内容可以是你的精选内容;

     

    ▷ 激发用户的探索欲,通过描述或者图片吸引用户注意力;

     

    ▷ 按照自己的产品目标,给用户提供清晰明确的下一步操作(查看详情、购买等)。

     

    如果某些特殊小程序在使用前一定需要用户登录,或者已经进行到需要用户登录的操作时,可以将 button 组件(其中 open-type 属性指定为 getUserInfo)放置到页面中,页面上可以大致说明以下要点:

     

    为什么需要我授权?

    需要我什么信息?

    授权后我得到什么好处呢?

     

    接下来在页面上放置一个明显的登录按钮, 建议这个页面上不要有额外的点击区域,以免分散用户注意力,让用户专注于登录这件事情。

     

    简单的开发建议

    1

    当用户打开小程序时访问第一个页面时,先通过 wx.login,获取用户 openID 。这时无需弹框授权,开发者拿到 openID 可以建立自身的帐号 ID。

    2

    在第一步中,拿到 openID 后,判断是新用户还是老用户。如果是老用户,可以直接登录;如果是新用户,可先在小程序首页展示你的信息服务,让用户对这个小程序有大概的了解,再引导用户进行下一步的操作。

    3

    当需要获取用户头像昵称的时候,对用户展示一个登录页面,这个页面只有一个最重要的操作,引导用户进行登录。

     

    小程序中,在页面中加入一个 button 按钮,并将 open-type 属性设置为 getUserInfo 。

     

    以小程序为例:

     

    <button open-type="getUserInfo" bindgetuserinfo="userInfoHandler">微信登录</button>

     

    对于功能较简单的小程序或者小游戏而言,如果不是必须要获得用户的头像昵称,建议可先通过wx.login 拿到 openID 后,使用 open-data 方式或者开放数据域的方式展示用户信息,整个过程都无需用户授权。

     

    Tips:

     

    1、在用户登录后,开发者需要存储用户的 unionID,而且建议只把 unionID 作为互通的用户标识,不要直接使用 unionID 作为用户 ID。因为一旦小程序迁移到其他的开放平台下,unionID 是会改变的,而 openID 是不变的。

     

    2、用 button 组件的方式获得用户授权后,调用 wx.getUserInfo 就可以直接获取用户信息。这个的意义在于获取过一次之后,用户有可能改昵称头像,因此为了及时同步,最好是定期获取用户信息。

     

    这里两个小提示:

     

    ▷ 定期使用 wx.getUserInfo 获取并更新用户的信息;

     

     如果用户授权过一次之后,又在设置中关掉了授权(或者本地删除了小程序),那这时再调用 wx.getUserInfo 也是不会成功的,需要重新获得授权

     

    相关开发文档参考:

     

    ▷ 小程序

    1、小程序wx.login

    2、button 组件,并将 open-type 指定为 getUserInfo 类型,获取用户基本信息

    3、open-data 展示用户基本信息

     

    ▷ 小游戏

    1、小游戏wx.login

    2、用户信息按钮 UserInfoButton

    3、开放数据域下的展示用户信息

     

    展开全文
  • 在18年4月25日小程序做了一次更新,小程序授权不再支持直接弹框获取用户信息授权了 微信小程序授权 获取用户信息里也做了说明 以下代码也已经做了更改 ---------------------------------------------------------...

    更新:

    在18年4月25日小程序做了一次更新,小程序授权不再支持直接弹框获取用户信息授权

    微信小程序授权 获取用户信息里也做了说明

    以下代码也已经做了更改

    --------------------------------------------------------------------------------------------------

    在实际的小程序开发中,往往需要用户授权登陆并获取用户的数据,

    小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系。

    官方API给出的是这样的

    https://developers.weixin.qq.com/miniprogram/dev/api/signature.htm

    说明:

    小程序调用wx.login() 获取 临时登录凭证code ,并回传到开发者服务器。
    开发者服务器以code换取 用户唯一标识openid会话密钥session_key

    之后开发者服务器可以根据用户标识来生成自定义登录态,用于后续业务逻辑中前后端交互时识别用户身份。

    具体API里说的很清楚了,下面直接上代码,具体用到什么会直接上链接

     

    具体流程(可直接看3)

    1、(客户端 JS部分)微信小程序客户端调用接口wx.login() 获取临时登录凭证(code)

            API:参数\登录凭证验证\接口说明

    //1、调用微信登录接口,获取code
    wx.login({
        success: function (r) {
            var code = r.code;//登录凭证
            if (code) {
                //2、调用获取用户信息接口
                //...
    
            } else {
                console.log('获取用户登录态失败!' + r.errMsg)
            }
        },
        fail: function () {
            callback(false)
        }
    })

    2、(客户端 JS部分)微信小程序客户端校验用户当前session_key是否有效,调用 wx.getUserInfo()接口获取 用户基本信息、encryptedData(用户敏感信息加密数据) 和 iv(加密算法的初始向量 )

    //1、调用微信登录接口,获取code
    wx.login({
        success: function (r) {
            var code = r.code;//登录凭证
            if (code) {
                //2、调用获取用户信息接口
                wx.getUserInfo({
                    success: function (res) {
                        console.log({encryptedData: res.encryptedData, iv: res.iv, code: code})
                        //3.解密用户信息 获取unionId
                        //...
                    },
                    fail: function () {
                        console.log('获取用户信息失败')
                    }
                })
    
            } else {
                console.log('获取用户登录态失败!' + r.errMsg)
            }
        },
        fail: function () {
            callback(false)
        }
    })

    3、(客户端 JS部分/WXML部分)将前面获取到的 code 、encryptedData、iv发送到自己的服务器(开发者服务器),通过自己的服务器(开发者服务器)解密获取信息

    <!--wxml-->
    <!-- 如果只是展示用户头像昵称,可以使用 <open-data /> 组件 -->
    <open-data type="userAvatarUrl"></open-data>
    <open-data type="userNickName"></open-data>
    <!-- 需要使用 button 来授权登录 -->
    <button wx:if="{{canIUse}}" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">授权登录</button>
    <view wx:else>请升级微信版本</view>
    //js
    Page({
      data: {
        canIUse: wx.canIUse('button.open-type.getUserInfo')
      },
      onLoad: function() {
        // 查看是否授权
        wx.getSetting({
          success: function(res){
            if (res.authSetting['scope.userInfo']) {
              // 已经授权,可以直接调用 getUserInfo 获取头像昵称
              wx.getUserInfo({
                success: function(res) {
                  console(res.userInfo)
                }
              })
            }
          }
        })
      },
      bindGetUserInfo: function (event) {
      console.log(event.detail.userInfo)
      //使用
      wx.getSetting({
        success: res => {
          if (res.authSetting['scope.userInfo']) {
            // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
            wx.login({
              success: function (res) {
                var code = res.code;//登录凭证
                if (code) {
                  //2、调用获取用户信息接口
                  wx.getUserInfo({
                    success: function (res) {
                      console.log({ encryptedData: res.encryptedData, iv: res.iv, code: code })
                      //3.请求自己的服务器,解密用户信息 获取unionId等加密信息
                      wx.request({
                        url: 'https://xxxx.com/wxsp/decodeUserInfo',//自己的服务接口地址
                        method: 'post',
                        header: {
                          'content-type': 'application/x-www-form-urlencoded'
                        },
                        data: { encryptedData: res.encryptedData, iv: res.iv, code: code },
                        success: function (data) {
    
                          //4.解密成功后 获取自己服务器返回的结果
                          if (data.data.status == 1) {
                            var userInfo_ = data.data.userInfo;
                            console.log(userInfo_)
                          } else {
                            console.log('解密失败')
                          }
    
                        },
                        fail: function () {
                          console.log('系统错误')
                        }
                      })
                    },
                    fail: function () {
                      console.log('获取用户信息失败')
                    }
                  })
    
                } else {
                  console.log('获取用户登录态失败!' + r.errMsg)
                }
              },
              fail: function () {
                console.log('登陆失败')
              }
            })
    
          } else {
            console.log('获取用户信息失败')
    
          }
    
        }
      })
    
    }
    })

    4、(服务端 java部分)自己的服务器发送code到微信服务器获取openid(用户唯一标识)和session_key(会话密钥),最后将encryptedData、iv、session_key通过AES解密获取到用户敏感数据 (整段复制即可无需修改)

    解密这里官方也给出了参照示例API,微信官方提供了多种编程语言的示例代码(点击下载)。每种语言类型的接口名字均一致。调用方式可以参照示例。但没有JAVA的,

    a、获取秘钥并处理解密的controller(这里用的是springMVC)

    /**
        * @Title: decodeUserInfo
        * @author:lizheng
        * @date:2018年3月25日
        * @Description: 解密用户敏感数据
        * @param encryptedData 明文,加密数据
         * @param iv   加密算法的初始向量
         * @param code  用户允许登录后,回调内容会带上 code(有效期五分钟),开发者需要将 code 发送到开发者服务器后台,使用code 换取 session_key api,将 code 换成 openid 和 session_key
         * @return
    	 */
    	   @SuppressWarnings({ "unchecked", "rawtypes" })
    	    @RequestMapping(value = "/decodeUserInfo", method = RequestMethod.POST)
    	   @ResponseBody
    	    public Map decodeUserInfo(String encryptedData, String iv, String code) {
    
    		Map map = new HashMap();
    
    		// 登录凭证不能为空
    		if (code == null || code.length() == 0) {
    			map.put("status", 0);
    			map.put("msg", "code 不能为空");
    			return map;
    		}
    
    		// 小程序唯一标识 (在微信小程序管理后台获取)
    		String wxspAppid = "wx18385lalalala";
    		// 小程序的 app secret (在微信小程序管理后台获取)
    		String wxspSecret = "bef47459d81a6eflalalalala";
    		// 授权(必填)
    		String grant_type = "authorization_code";
    
    		 1、向微信服务器 使用登录凭证 code 获取 session_key 和 openid
    		 
    		// 请求参数
    		String params = "appid=" + wxspAppid + "&secret=" + wxspSecret + "&js_code=" + code + "&grant_type="
    				+ grant_type;
    		// 发送请求
    		String sr = HttpRequest.sendGet("https://api.weixin.qq.com/sns/jscode2session", params);
    		// 解析相应内容(转换成json对象)
    		JSONObject json = new JSONObject(sr);
    		// 获取会话密钥(session_key)
    		String session_key = json.get("session_key").toString();
    		// 用户的唯一标识(openid)
    		String openid = (String) json.get("openid");
    
    		 2、对encryptedData加密数据进行AES解密 
    		try {
    			String result = AesCbcUtil.decrypt(encryptedData, session_key, iv, "UTF-8");
    			if (null != result && result.length() > 0) {
    				map.put("status", 1);
    				map.put("msg", "解密成功");
    
    				JSONObject userInfoJSON = new JSONObject(result);
    				Map userInfo = new HashMap();
    				userInfo.put("openId", userInfoJSON.get("openId"));
    				userInfo.put("nickName", userInfoJSON.get("nickName"));
    				userInfo.put("gender", userInfoJSON.get("gender"));
    				userInfo.put("city", userInfoJSON.get("city"));
    				userInfo.put("province", userInfoJSON.get("province"));
    				userInfo.put("country", userInfoJSON.get("country"));
    				userInfo.put("avatarUrl", userInfoJSON.get("avatarUrl"));
    				// 解密unionId & openId;
    
    				userInfo.put("unionId", userInfoJSON.get("unionId"));
    				map.put("userInfo", userInfo);
    			} else {
    				map.put("status", 0);
    				map.put("msg", "解密失败");
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		return map;
    	}    

     

    添加两个工具类:

    b、AesCbcUtil.java 工具类 (整段复制即可无需修改)

    package com.yfs.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;
    
    /**
     * Created by yfs on 2018/3/25.
     * <p>
     * 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 {
    //        initialize();
    
            //被加密的数据
            byte[] dataByte = Base64.decodeBase64(data);
            //加密秘钥
            byte[] keyByte = Base64.decodeBase64(key);
            //偏移量
            byte[] ivByte = Base64.decodeBase64(iv);
    
    
            try {
                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
    
                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;
        }
    
    }

    c、HttpRequest.java 工具类 (整段复制即可无需修改)

    package com.yfs.util;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.URL;
    import java.net.URLConnection;
    import java.util.List;
    import java.util.Map;
    
    public class HttpRequest {
    
        public static void main(String[] args) {
            //发送 GET 请求
            String s=HttpRequest.sendGet("http://v.qq.com/x/cover/kvehb7okfxqstmc.html?vid=e01957zem6o", "");
            System.out.println(s);
    
    //        //发送 POST 请求
    //        String sr=HttpRequest.sendPost("http://www.toutiao.com/stream/widget/local_weather/data/?city=%E4%B8%8A%E6%B5%B7", "");
    //        JSONObject json = JSONObject.fromObject(sr);
    //        System.out.println(json.get("data"));
        }
    
        /**
         * 向指定URL发送GET方法的请求
         * 
         * @param url
         *            发送请求的URL
         * @param param
         *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
         * @return URL 所代表远程资源的响应结果
         */
        public static String sendGet(String url, String param) {
            String result = "";
            BufferedReader in = null;
            try {
                String urlNameString = url + "?" + param;
                URL realUrl = new URL(urlNameString);
                // 打开和URL之间的连接
                URLConnection connection = realUrl.openConnection();
                // 设置通用的请求属性
                connection.setRequestProperty("accept", "*/*");
                connection.setRequestProperty("connection", "Keep-Alive");
                connection.setRequestProperty("user-agent",
                        "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
                // 建立实际的连接
                connection.connect();
                // 获取所有响应头字段
                Map<String, List<String>> map = connection.getHeaderFields();
                // 遍历所有的响应头字段
                for (String key : map.keySet()) {
                    System.out.println(key + "--->" + map.get(key));
                }
                // 定义 BufferedReader输入流来读取URL的响应
                in = new BufferedReader(new InputStreamReader(
                        connection.getInputStream()));
                String line;
                while ((line = in.readLine()) != null) {
                    result += line;
                }
            } catch (Exception e) {
                System.out.println("发送GET请求出现异常!" + e);
                e.printStackTrace();
            }
            // 使用finally块来关闭输入流
            finally {
                try {
                    if (in != null) {
                        in.close();
                    }
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
            return result;
        }
    
        /**
         * 向指定 URL 发送POST方法的请求
         * 
         * @param url
         *            发送请求的 URL
         * @param param
         *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
         * @return 所代表远程资源的响应结果
         */
        public static String sendPost(String url, String param) {
            PrintWriter out = null;
            BufferedReader in = null;
            String result = "";
            try {
                URL realUrl = new URL(url);
                // 打开和URL之间的连接
                URLConnection conn = realUrl.openConnection();
                // 设置通用的请求属性
                conn.setRequestProperty("accept", "*/*");
                conn.setRequestProperty("connection", "Keep-Alive");
                conn.setRequestProperty("user-agent",
                        "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
                // 发送POST请求必须设置如下两行
                conn.setDoOutput(true);
                conn.setDoInput(true);
                // 获取URLConnection对象对应的输出流
                out = new PrintWriter(conn.getOutputStream());
                // 发送请求参数
                out.print(param);
                // flush输出流的缓冲
                out.flush();
                // 定义BufferedReader输入流来读取URL的响应
                in = new BufferedReader(
                        new InputStreamReader(conn.getInputStream()));
                String line;
                while ((line = in.readLine()) != null) {
                    result += line;
                }
            } catch (Exception e) {
                System.out.println("发送 POST 请求出现异常!"+e);
                e.printStackTrace();
            }
            //使用finally块来关闭输出流、输入流
            finally{
                try{
                    if(out!=null){
                        out.close();
                    }
                    if(in!=null){
                        in.close();
                    }
                }
                catch(IOException ex){
                    ex.printStackTrace();
                }
            }
            return result;
        }    
    }

    备注

    1. 代码中需要用到的jar包,请自行下载并添加到项目中。
    2. 这里需要注意的是,AES解密的时候需要用到javax.crypto.*包的类,在jdk的 jce.jar中提供,是jdk自带的库。如果是MAVEN项目,则需要在pom.xml文件中配置指定编译路径jce.jar

     

    总结

    有一点需要注意的是,要对接已有的用户系统需要用到unionId,如果通过以上方法获取不到unionId,那么你就要去检查一下你的微信开放平台(微信开放平台)是否有绑定微信小程序.

    UnionID获取途径

    登录微信开放平台(open.weixin.qq.com) – 帐号中心 – 开发者资质认证

     

    绑定流程:

    登录微信开放平台(open.weixin.qq.com)—管理中心—公众帐号—绑定公众帐号

     

    打印一下

     

    展开全文
  • linux查看当前用户信息及其用户切换

    万次阅读 2019-07-06 17:35:14
    linux查看当前用户信息及其用户切换 一、查看用户信息 作为系统管理员,你可能经常会(在某个时候)需要查看系统中有哪些用户正在活动。有些时候,你甚至需要知道他(她)们正在做什么。本文为我们总结了4种查看系统...

    linux查看当前用户信息及其用户切换

    一、查看用户信息

    作为系统管理员,你可能经常会(在某个时候)需要查看系统中有哪些用户正在活动。有些时候,你甚至需要知道他(她)们正在做什么。本文为我们总结了4种查看系统用户信息(通过编号(ID))的方法。

    1. 使用w命令查看登录用户正在使用的进程信息
      w命令用于显示已经登录系统的用户的名称,以及他们正在做的事。该命令所使用的信息来源于/var/run/utmp文件。w命令输出的信息包括:
      用户名称
      用户的机器名称或tty号
      远程主机地址
      用户登录系统的时间
      空闲时间(作用不大)
      附加到tty(终端)的进程所用的时间(JCPU时间)
      当前进程所用时间(PCPU时间)
      用户当前正在使用的命令
      w命令还可以使用以下选项
      -h忽略头文件信息
      -u显示结果的加载时间
      -s不显示JCPU, PCPU, 登录时间
    [root@localhost /]# w
     11:29:48 up  3:37,  3 users,  load average: 0.00, 0.00, 0.00
    USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
    root     tty1     :0               07:55    3:37m  2.14s  2.14s /usr/bin/Xorg :0 -nr -verb
    root     pts/0    192.168.19.1     09:42    0.00s  0.38s  0.00s w
    root     pts/1    192.168.19.1     09:48    3:31   0.08s  0.08s -bash
    [root@localhost /]# w -h
    root     tty1     :0               07:55    3:37m  2.14s  2.14s /usr/bin/Xorg :0 -nr -verb
    root     pts/0    192.168.19.1     09:42    0.00s  0.38s  0.00s w -h
    root     pts/1    192.168.19.1     09:48    3:35   0.08s  0.08s -bash
    [root@localhost /]# w -u
     11:29:56 up  3:38,  3 users,  load average: 0.00, 0.00, 0.00
    USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
    root     tty1     :0               07:55    3:37m  2.14s  2.14s /usr/bin/Xorg :0 -nr -verb
    root     pts/0    192.168.19.1     09:42    0.00s  0.38s  0.00s w -u
    root     pts/1    192.168.19.1     09:48    3:39   0.08s  0.08s -bash
    [root@localhost /]# w -s
     11:29:59 up  3:38,  3 users,  load average: 0.00, 0.00, 0.00
    USER     TTY      FROM               IDLE WHAT
    root     tty1     :0                3:37m /usr/bin/Xorg :0 -nr -verbose -audit 4 -auth /
    root     pts/0    192.168.19.1      0.00s w -s
    root     pts/1    192.168.19.1      3:42  -bash
    [root@localhost /]#
    
    1. 使用who命令查看(登录)用户名称及所启动的进程
      who命令用于列举出当前已登录系统的用户名称。其输出为:用户名、tty号、时间日期、主机地址。
    [root@localhost /]# who
    root     tty1         2017-11-12 07:55 (:0)
    root     pts/0        2017-11-12 09:42 (192.168.19.1)
    root     pts/1        2017-11-12 09:48 (192.168.19.1)
    [root@localhost /]# 
    

    如果只希望列出用户,可以使用如下语句:

    [root@localhost /]# who | cut -d ' ' -f1 | sort
    root
    root
    root
    [root@localhost /]# who | cut -d ' ' -f1 | sort | uniq
    root
    [root@localhost /]#
    

    补充:users命令,可用于打印输出登录服务器的用户名称。该命令除了有help和version选项外,再没有其他选项。如果某用户使用了多个终端,则相应的会显示多个重复的用户名。

    [root@localhost /]# users
    root root root
    [root@localhost /]#
    
    1. 使用whoami命令查看你所使用的登录名称
      whoami命令用于显示登入的用户名。
    [root@localhost /]# whoami
    root
    [root@localhost /]# who am i
    root     pts/0        2017-11-12 09:42 (192.168.19.1)
    [root@localhost /]# 
    

    whoami命令的执行效果和id -un的效果完全一样,例如:

    [root@localhost /]# id -un
    root
    [root@localhost /]#
    

    whoami命令能显示当前登入的用户名称,以及当前所使用的tty信息。该命令的输出结果包括如下内容:用户名、tty名、当前时间日期,同时还包括用户登录系统所使用的链接地址。

    [root@localhost /]# who am i
    root     pts/0        2017-11-12 09:42 (192.168.19.1)
    [root@localhost /]# who mom likes
    root     pts/0        2017-11-12 09:42 (192.168.19.1)
    [root@localhost /]# 
    

    当然,如果你使用su命令改变用户,则该命令(whoami)所显示的结果将随之改变。
    4. ** 随时查看系统的历史信息(曾经使用过系统的用户信息)**
    last命令可用于显示特定用户登录系统的历史记录。如果没有指定任何参数,则显示所有用户的历史信息。在默认情况下,这些信息(所显示的信息)将来源于/var/log/wtmp文件。该命令的输出结果包含以下几列信息:
    用户名称
    tty设备号
    历史登录时间日期
    登出时间日期
    总工作时间

    [root@localhost /]# last root
    root     pts/1        192.168.19.1     Sun Nov 12 09:48   still logged in   
    root     pts/0        192.168.19.1     Sun Nov 12 09:42   still logged in   
    root     pts/0        192.168.19.1     Sun Nov 12 07:56 - 09:42  (01:45)    
    root     tty1         :0               Sun Nov 12 07:55   still logged in   
    root     pts/1        192.168.19.1     Thu Nov  9 11:02 - 11:28  (00:26)    
    root     pts/0        192.168.19.1     Thu Nov  9 10:47 - 11:28  (00:40)    
    root     tty1         :0               Thu Nov  9 10:45 - 11:28  (00:42)    
    root     pts/1        192.168.19.1     Thu Nov  9 09:57 - down   (00:23)    
    root     pts/0        192.168.19.1     Thu Nov  9 08:55 - down   (01:24)    
    root     pts/1        192.168.19.1     Thu Nov  9 07:13 - 08:55  (01:41)    
    root     pts/0        192.168.19.1     Thu Nov  9 03:56 - 08:28  (04:32)    
    root     pts/1        192.168.19.1     Thu Nov  9 03:04 - 03:54  (00:49)    
    root     pts/0        192.168.19.1     Thu Nov  9 03:01 - 03:54  (00:52)    
    root     pts/1        192.168.19.1     Thu Nov  9 02:59 - 02:59  (00:00)    
    root     pts/0        192.168.19.1     Thu Nov  9 02:56 - 02:59  (00:02)    
    root     tty1         :0               Thu Nov  9 02:50 - down   (07:30)    
    
    wtmp begins Thu Nov  9 02:47:58 2017
    

    二、 用户切换

    su((switch user的缩写)
    格式为:su [ - ] username,后面可以跟 - ,也可以不跟, 区别如下:

    su - charles_1, 此时用户切换到charles_1后,环境变量也会跟着更改。也就是说:当输入java -version的时候,jdk版本为1.7,而不是1.8。 之所以是1.7,是因为在进行切换用户的时候,su命令后面加了横杠。如果不加横杠,那么当前用户是:charles_1,但环境变量还是root用户的环境变量。
    
    su charles_1, 此时用户切换到charles_1后,环境变量不会跟着改变,还是root用户的环境变量。输入java -version的时候,jdk版本为1.8
    

    》》》博主长期更新学习心得,推荐点赞关注!!!
    》》》若有错误之处,请在评论区留言,谢谢!!!

    展开全文
  • 这是我们学校的软件工程课程设计的题目,要求自行编写爬虫或者利用开放的API获取新浪微博、知乎等社交网站的用户信息,利用数据挖掘的相关算法进行分析, 从大规模的用户群体中, 分别找出其中具有海淘或母婴购物意向...
  • 客户信息管理系统7—客户信息的修改 4、功能四:客户信息的修改: (1)修改流程   (2)修改分析 选择要修改的客户信息,然后把要修改的信息显示在表单上;然后在该表单上进行修改信息,然后点击修改完成,然后重新...
  • spring security 获取用户信息

    万次阅读 多人点赞 2018-02-19 17:09:51
    spring security 获取用户信息 本文描述在spring security中如何获取用户信息。分别介绍几种常用的方法实现。 通过Bean获取用户 获取当前认证用户(authenticated principal)最简单的方式是通过...
  • 客户信息管理系统4—客户信息的查询 2、功能二:客户信息的查询 (1)查询的流程 (2)实现代码 2.1代码组成 index.jsp+ findAllCustomer.jsp+ FindAllServlet +CustomersService + CustomersDao+ ...
  • 客户信息管理系统8—客户信息的模糊查询 5、功能五:模糊查询(条件查询) (1)条件查询说明 条件查询:需要 用户去选择按照什么条件查询, 以及查询的具体的值 一般条件 可以由用户选择 在服务器端 根据用户选定...
  • 微信小程序 获取用户信息(包括openId等敏感信息)

    万次阅读 多人点赞 2017-08-07 17:34:01
    获取用户的基本信息 wx.getUserInfo(OBJECT)获取用户信息 wx.getUserInfo({ success: function(res) { var userInfo = res.userInfo //用户基本信息 var nickName = userInfo.nickName //用户名
  • 微信用户信息获取

    千次阅读 2017-12-26 17:11:05
    微信用户信息获取有两种方式:第一种利用普通access_token和openid进行获取;第二种利用网页授权的access_token进行获取。本文主要介绍第二种方式,第一种方式在微信网页授权access_token和普通access_token区别中做...
  • MySql之查看用户信息

    万次阅读 2019-06-11 21:49:33
    下面来记录并分享下mysql数据库查看用户信息的语句: 用root用户登录,查看用户信息: select user, host, password from mysql.user
  • package CustomerManagementSystem;... //描述客户信息 private String name; private String sex; private String phone; //默认构造函数 public Customer() { super(); } //利用构造函...
  • author:咔咔 wechat:fangkangfk ... ...在用户登录成功后,我们会将用户信息存储...我们在用户登录后会储存很多的用户信息,也会设置很多的session的key,后期项目不方便维护和管理 这就需要创建一个工具类来管...
  • 博主突发奇想,想把所有的QQ用户信息给爬下来,但是QQ肯定没有这样的接口(数据都是钱啊,谁会把钱免费送给人),那么该怎么办?既然此路不通,那有没有其他方法呢?冥思苦想之后,博主突然想到QQ是可以根据QQ号码...
  • 支付宝获取用户信息

    千次阅读 2018-09-07 17:30:16
    我们项目通过扫码支付,HTML5与后台交互,先获取...首先:获取用户信息  $appid=config('alipay_id'); $redirect_uri = urlencode ('你的回调地址'); $url ="https://openauth.alipay.com/oauth2/publicAp...
  • 小程序登录获取用户信息及授权手机号方法

    万次阅读 多人点赞 2019-02-18 13:42:17
    小程序登录,是现在小程序里面很普遍的一个功能,因为官方提供的方法,可以一键获取到用户信息,一键拿到手机号,本篇主要记录,本人开发小程序时,做登录过程中遇到的问题及解决方法)。 小程序登录 wxml: wxml...
  • JavaWeb 简单实现客户信息管理系统

    千次阅读 2017-07-08 22:29:00
    项目介绍 本项目使用Jsp+Servlet...搜索客户信息:根据用户的输入查询客户信息 编辑客户信息:编辑当前客户信息 删除客户信息:根据客户id删除客户信息 开发工具 Intellij IDEA 2017 MySQL Tomcat 8.0 ...
  • 我们在开发小程序时,如果想获取用户信息,就需要获取用的授权,如果用户误点了拒绝授权,我们怎么样去正确的引导用户重新授权呢。今天就来给大家讲讲如果正确的引导用户授权。 老规矩,先看效果图 从上图可以看出...
  • 使用shiro的时候,更新用户头像时发现,数据库信息已经更新了,但是页面上的头像没有发生变化(用户信息直接从subject中获取的) public static UserDO getUser() { Object object = getSubjct().getPrincipal(); ...
  • IDEA中实现用户信息修改功能

    千次阅读 2017-11-29 17:44:56
    实现用户信息修改功能,首先从数据库中读取用户个人信息在前台页面展示,通过修改用户某些字段信息,以form表单提交的方式,将修改后用户信息进行保存到数据库,同时页面无刷新显示更新后的用户数据信息
  • 获取客户信息SQL

    千次阅读 2013-12-06 20:16:37
    /*取客户信息SQL*/ --客户信息 SELECT hou.name 业务实体, hca.account_number 客户编号, hp.party_name 客户名称, arp_addr_pkg.format_address(hl.address_style, hl.address1
  • Spring Security OAUTH2 获取用户信息

    万次阅读 热门讨论 2018-08-19 01:15:48
    1.user-info-uri 与 token-info-uri 作用:二者皆是为了check token,并且顺带返回...user-info-uri原理是在授权服务器认证后将认证信息Principal通过形参绑定的方法通过URL的方式获取用户信息。当然它也有配套的Us...
  • 微信小程序授权登录 获取用户信息与手机号

    万次阅读 多人点赞 2020-01-04 16:34:36
    微信小程序授权登录 获取用户信息与手机号 很多不看文档的总有一些奇葩想法,小程序能直接获取用户信息吗,小程序能直接获取手机号么 答案是no 公告地址 微信小程序,逐渐向用户个人隐私保护上优化,所以开发...
  • 支付宝 网页授权 获取用户信息

    万次阅读 多人点赞 2017-03-20 15:26:17
    ****** 支付宝 网页授权 获取用户信息(昵称,头像等)****** 最近有个项目 需要获取到支付宝的头像和昵称作为互动数据,作为php新人,对于看文档来说 很是痛苦,网上也没有很多关于支付宝网页授权接口的详细信息。...
  • 系统中使用shrio登录后获取当前登陆的用户很简单 只需要一句代码 这...这段代码在系统中任何地方都可以使用,但是由于是在session中获取的,如果说用户修改了用户的个人信息,会发现明明数据库已经修改成功了,但是...
  • 当更改用户信息的时候,发现subject.却还是原来的信息, 没有直接的办法更改,只能给当前用户切换身份,切换一个认证信息给安全管理器。 当更改用户信息后,调用setUser方法,UserInfo是原来放在...
  • 新浪微博手机端用户信息和微博信息用户信息:包括用户ID、用户名、微博数、粉丝数、关注数等。 微博信息:包括转发或原创、点赞数、转发数、评论数、发布时间、微博内容等。 安装过程: 1.先安装Python环境,...
  • QT项目六:简易客户信息管理系统

    万次阅读 多人点赞 2018-04-21 18:04:33
    1,简介刚与几位朋友合伙创业那会,因为我在公司负责软件,销售问我有没有什么软件可以管理他的客户信息,不用太复杂。我了解了一下具体需求,就是可以把客户按照地域、类型等进行分类,然后存储一些基本信息,比如...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,720,095
精华内容 1,888,038
关键字:

用户信息