2016-10-27 16:45:22 xiaoyezihanghui 阅读数 5057
  • JavaWeb实战开发

    本课程详细讲解了以下内容:     1.jsp环境搭建及入门、虚拟路径和虚拟主机、JSP执行流程     2.使用Eclipse快速开发JSP、编码问题、JSP页面元素以及request对象、使用request对象实现注册示例     3.请求方式的编码问题、response、请求转发和重定向、cookie、session执行机制、session共享问题      4.session与cookie问题及application、cookie补充说明及四种范围对象作用域      5.JDBC原理及使用Statement访问数据库、使用JDBC切换数据库以及PreparedStatement的使用、Statement与PreparedStatement的区别      6.JDBC调用存储过程和存储函数、JDBC处理大文本CLOB及二进制BLOB类型数据      7.JSP访问数据库、JavaBean(封装数据和封装业务逻辑)      8.MVC模式与Servlet执行流程、Servlet25与Servlet30的使用、ServletAPI详解与源码分析      9.MVC案例、三层架构详解、乱码问题以及三层代码流程解析、完善Service和Dao、完善View、优化用户体验、优化三层(加入接口和DBUtil)     1 0.Web调试及bug修复、分页SQL(Oracle、MySQL、SQLSERVER)      11.分页业务逻辑层和数据访问层Service、Dao、分页表示层Jsp、Servlet      12.文件上传及注意问题、控制文件上传类型和大小、下载、各浏览器下载乱码问题      13.EL表达式语法、点操作符和中括号操作符、EL运算、隐式对象、JSTL基础及set、out、remove      14.过滤器、过滤器通配符、过滤器链、监听器      15.session绑定解绑、钝化活化      16.以及Ajax的各种应用      17. Idea环境下的Java Web开发

    3688 人正在学习 去看看 颜群


释: 我是订阅号,申请的微信开发测试账号,操作授权登录


1.  下载web开发工具


2.  在公众号列表中, 开发者工具-》web开发工具-> 绑定开发者账号 -》输入你的微信号(微信号需关注公众号才可绑定),邀请绑定在微信客户端确认邀请即可


3.  在测试管理账号中, 网页授权获取用户基本信息  接口,点击修改  填充(授权回调页面域名),沙盒测试环境不限ip和域名,我填充的ip ( 注释: ip填充只需 如192.168.0.1:port,前缀不需要http,此坑已踩)


4.  授权链接 https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx58caa75dbeb054aa&redirect_uri=http://192.168.0.1:8014/wechat_login&response_type=code&scope=snsapi_userinfo&state=1   回调按照自己的需求更改即可

2018-07-17 17:30:12 godhexin 阅读数 624
  • JavaWeb实战开发

    本课程详细讲解了以下内容:     1.jsp环境搭建及入门、虚拟路径和虚拟主机、JSP执行流程     2.使用Eclipse快速开发JSP、编码问题、JSP页面元素以及request对象、使用request对象实现注册示例     3.请求方式的编码问题、response、请求转发和重定向、cookie、session执行机制、session共享问题      4.session与cookie问题及application、cookie补充说明及四种范围对象作用域      5.JDBC原理及使用Statement访问数据库、使用JDBC切换数据库以及PreparedStatement的使用、Statement与PreparedStatement的区别      6.JDBC调用存储过程和存储函数、JDBC处理大文本CLOB及二进制BLOB类型数据      7.JSP访问数据库、JavaBean(封装数据和封装业务逻辑)      8.MVC模式与Servlet执行流程、Servlet25与Servlet30的使用、ServletAPI详解与源码分析      9.MVC案例、三层架构详解、乱码问题以及三层代码流程解析、完善Service和Dao、完善View、优化用户体验、优化三层(加入接口和DBUtil)     1 0.Web调试及bug修复、分页SQL(Oracle、MySQL、SQLSERVER)      11.分页业务逻辑层和数据访问层Service、Dao、分页表示层Jsp、Servlet      12.文件上传及注意问题、控制文件上传类型和大小、下载、各浏览器下载乱码问题      13.EL表达式语法、点操作符和中括号操作符、EL运算、隐式对象、JSTL基础及set、out、remove      14.过滤器、过滤器通配符、过滤器链、监听器      15.session绑定解绑、钝化活化      16.以及Ajax的各种应用      17. Idea环境下的Java Web开发

    3688 人正在学习 去看看 颜群

当我们利用服务器和代码成为高级开发之后,微信公众平台编辑好的当用户关注时发送给用户的语句就会失效,此时应该怎么办,接下来,用代码来来教你实现。首先先看一下官方的开发文档:

关注/取消关注事件

用户在关注与取消关注公众号时,微信会把这个事件推送到开发者填写的URL。方便开发者给用户下发欢迎消息或者做帐号的解绑。为保护用户数据隐私,开发者收到用户取消关注事件时需要删除该用户的所有信息。

微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次。

关于重试的消息排重,推荐使用FromUserName + CreateTime 排重。

假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。

推送XML数据包示例:

<xml><ToUserName>< ![CDATA[toUser] ]></ToUserName><FromUserName>< ![CDATA[FromUser] ]></FromUserName><CreateTime>123456789</CreateTime><MsgType>< ![CDATA[event] ]></MsgType><Event>< ![CDATA[subscribe] ]></Event></xml>

参数说明:

参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType 消息类型,event
Event 事件类型,subscribe(订阅)、unsubscribe(取消订阅)

根据开发文档书写代码如何:

1.先创建实体类:

public class TextMessage {


    private  String ToUserName;

    private  String FromUserName;

    private  Long CreateTime;

    private  String MsgType;

    private  String Content;

    public String getContent() {
        return Content;
    }

    public void setContent(String content) {
        Content = content;
    }

    public String getToUserName() {
        return ToUserName;
    }

    public void setToUserName(String toUserName) {
        ToUserName = toUserName;
    }

    public String getFromUserName() {
        return FromUserName;
    }

    public void setFromUserName(String fromUserName) {
        FromUserName = fromUserName;
    }

    public Long getCreateTime() {
        return CreateTime;
    }

    public void setCreateTime(Long createTime) {
        CreateTime = createTime;
    }

    public String getMsgType() {
        return MsgType;
    }

    public void setMsgType(String msgType) {
        MsgType = msgType;
    }
}

2.检验类型:

public class MessageImpl {


    public String messgage(Map<String,String> requestMap){

        String textMsgXml = "";

         if (requestMap.size()>0) {

            String fromUserName = requestMap.get("FromUserName");
            // 公众帐号
            String toUserName = requestMap.get("ToUserName");
            // 消息类型
            String msgType = requestMap.get("MsgType");

            String eventKey = requestMap.get("EventKey");

            String event = requestMap.get("Event");
               3 if (event.equals("subscribe")) {
                 TextMessage textMessage = new TextMessage();
                textMessage.setToUserName(fromUserName);
                textMessage.setFromUserName(toUserName);
                textMessage.setCreateTime(new Date().getTime());
                textMessage.setMsgType("text");
                textMessage.setContent("你好");
                XStream xStream = new XStream();
                xStream.alias("xml", textMessage.getClass());
                textMsgXml = xStream.toXML(textMessage);
             }
         }
        return textMsgXml;
    }
}

3.获取微信服务器发来的信息:

@RequestMapping(value = "/signature")
@ResponseBody
public  String xmlToMap(HttpServletRequest request,@RequestParam String signature, @RequestParam String timestamp,
                        @RequestParam String nonce) {
    Map<String, String> map = new HashMap<String, String>();
    try {
        SAXReader reader = new SAXReader();
        InputStream ins = null;
        try {
            ins = request.getInputStream();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        Document doc = null;
        try {
            doc = reader.read(ins);
        } catch (DocumentException e1) {
            e1.printStackTrace();
        }
        Element root = doc.getRootElement();
        @SuppressWarnings("unchecked")
        List<Element> list = root.elements();
        for (Element e : list) {
            map.put(e.getName(), e.getText());
        }
        try {
            ins.close();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }catch (Exception e){

        PlatformLogger.error("错误信息",e);
    }

    return messageImpl.messgage(map);

}

这样有人关注的时候你可以自定义发送的语句了。

更多java的知识扫描下方二维码关注公众号,每天更新哦。

2018-05-07 16:58:05 qq_23543983 阅读数 8310
  • JavaWeb实战开发

    本课程详细讲解了以下内容:     1.jsp环境搭建及入门、虚拟路径和虚拟主机、JSP执行流程     2.使用Eclipse快速开发JSP、编码问题、JSP页面元素以及request对象、使用request对象实现注册示例     3.请求方式的编码问题、response、请求转发和重定向、cookie、session执行机制、session共享问题      4.session与cookie问题及application、cookie补充说明及四种范围对象作用域      5.JDBC原理及使用Statement访问数据库、使用JDBC切换数据库以及PreparedStatement的使用、Statement与PreparedStatement的区别      6.JDBC调用存储过程和存储函数、JDBC处理大文本CLOB及二进制BLOB类型数据      7.JSP访问数据库、JavaBean(封装数据和封装业务逻辑)      8.MVC模式与Servlet执行流程、Servlet25与Servlet30的使用、ServletAPI详解与源码分析      9.MVC案例、三层架构详解、乱码问题以及三层代码流程解析、完善Service和Dao、完善View、优化用户体验、优化三层(加入接口和DBUtil)     1 0.Web调试及bug修复、分页SQL(Oracle、MySQL、SQLSERVER)      11.分页业务逻辑层和数据访问层Service、Dao、分页表示层Jsp、Servlet      12.文件上传及注意问题、控制文件上传类型和大小、下载、各浏览器下载乱码问题      13.EL表达式语法、点操作符和中括号操作符、EL运算、隐式对象、JSTL基础及set、out、remove      14.过滤器、过滤器通配符、过滤器链、监听器      15.session绑定解绑、钝化活化      16.以及Ajax的各种应用      17. Idea环境下的Java Web开发

    3688 人正在学习 去看看 颜群

关注/取消关注事件

用户在关注与取消关注公众号时,微信会把这个事件推送到开发者填写的URL。方便开发者给用户下发欢迎消息或者做帐号的解绑。

微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次。

关于重试的消息排重,推荐使用FromUserName + CreateTime 排重。

假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。

推送XML数据包示例:

<xml><ToUserName>< ![CDATA[toUser] ]></ToUserName><FromUserName>< ![CDATA[FromUser] ]></FromUserName><CreateTime>123456789</CreateTime><MsgType>< ![CDATA[event] ]></MsgType><Event>< ![CDATA[subscribe] ]></Event></xml>

参数说明:

参数描述
ToUserName开发者微信号
FromUserName发送方帐号(一个OpenID)
CreateTime消息创建时间 (整型)
MsgType消息类型,event
Event事件类型,subscribe(订阅)、unsubscribe(取消订阅)

回复图文消息

<xml><ToUserName>< ![CDATA[toUser] ]></ToUserName><FromUserName>< ![CDATA[fromUser] ]></FromUserName><CreateTime>12345678</CreateTime><MsgType>< ![CDATA[news] ]></MsgType><ArticleCount>2</ArticleCount><Articles><item><Title>< ![CDATA[title1] ]></Title> <Description>< ![CDATA[description1] ]></Description><PicUrl>< ![CDATA[picurl] ]></PicUrl><Url>< ![CDATA[url] ]></Url></item><item><Title>< ![CDATA[title] ]></Title><Description>< ![CDATA[description] ]></Description><PicUrl>< ![CDATA[picurl] ]></PicUrl><Url>< ![CDATA[url] ]></Url></item></Articles></xml>
参数是否必须说明
ToUserName接收方帐号(收到的OpenID)
FromUserName开发者微信号
CreateTime消息创建时间 (整型)
MsgTypenews
ArticleCount图文消息个数,限制为8条以内
Articles多条图文消息信息,默认第一个item为大图,注意,如果图文数超过8,则将会无响应
Title图文消息标题
Description图文消息描述
PicUrl图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200
Url点击图文消息跳转链接
详细代码如下
News.java
public class News {
    private String Title;//图文标题
    private String Description;//图文描述
    private String PicUrl;//图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200
    private String Url;//点击图文消息跳转链接

    public News(String title, String description, String picUrl, String url) {
        this.Title = title;
        this.Description = description;
        this.PicUrl = picUrl;
        this.Url = url;
    }
    public News(){super();}

    public String getTitle() {
        return Title;
    }

    public void setTitle(String title) {
        this.Title = title;
    }

    public String getDescription() {
        return Description;
    }

    public void setDescription(String description) {
        this.Description = description;
    }

    public String getPicUrl() {
        return PicUrl;
    }

    public void setPicUrl(String picUrl) {
        this.PicUrl = picUrl;
    }

    public String getUrl() {
        return Url;
    }

    public void setUrl(String url) {
        this.Url = url;
    }
}

NewsMessage.java

public class NewsMessage extends BaseMessage {
    private int ArticleCount;//图文消息个数,限制为8条以内
    private List<News> Articles;//多条图文消息信息,默认第一个item为大图,注意,如果图文数超过8,则将会无响应
    public NewsMessage(String toUserName, String fromUserName, Long createTime, String msgType, Integer articleCount, List<News> articles) {
        super(toUserName, fromUserName, createTime, msgType);
        this.ArticleCount = articleCount;
        this.Articles = articles;
    }

    public NewsMessage() {
        super();
    }


    public int getArticleCount() {
        return ArticleCount;
    }

    public void setArticleCount(int articleCount) {
        this.ArticleCount = articleCount;
    }

    public List<News> getArticles() {
        return Articles;
    }

    public void setArticles(List<News> articles) {
        this.Articles = articles;
    }
}

初始化图文消息:

   /**
     * 初始化图文消息
     */
    public static String initNewsMessage(String toUSerName, String fromUserName) {
        List<News> newsList = new ArrayList<News>();
        NewsMessage newsMessage = new NewsMessage();
        //组建一条图文↓ ↓ ↓
        News newsItem = new News();
        newsItem.setTitle("欢迎关注我的公众号");
        newsItem.setDescription("进行操作之前请先注册!");
        newsItem.setPicUrl(WXConstants.BASE_SERVER + "/image/wx/login_article_cover.png");
        newsItem.setUrl("https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WXConstants.APPID + "&redirect_uri=" + WXConstants.BASE_SERVER + "/wxuser/toRegister&response_type=code&scope=snsapi_base&state=BINDFACE#wechat_redirect");
        newsList.add(newsItem);
        //组装图文消息相关信息
        newsMessage.setToUserName(fromUserName);
        newsMessage.setFromUserName(toUSerName);
        newsMessage.setCreateTime(new Date().getTime());
        newsMessage.setMsgType(WXConstants.MESSAGE_NEWS);
        newsMessage.setArticles(newsList);
        newsMessage.setArticleCount(newsList.size());
        //调用newsMessageToXml将图文消息转化为XML结构并返回
        return MessageUtil.newsMessageToXml(newsMessage);
    }
    /**
     * 图文消息转XML结构方法
     */
    public static String newsMessageToXml(NewsMessage message) {
        XStream xs = new XStream();
        //由于转换后xml根节点默认为class类,需转化为<xml>
        xs.alias("xml", message.getClass());
        xs.alias("item", new News().getClass());
        return xs.toXML(message);
    }

测试关注:

@Controller
@RequestMapping("/wechat")
public class WxController {

    private final static String MEDIATYPE_CHARSET_JSON_UTF8 = MediaType.APPLICATION_JSON_VALUE + ";charset=UTF-8";
    private static Logger log = LoggerFactory.getLogger(WxController.class);

    @RequestMapping(value = "/chat", method = {RequestMethod.GET, RequestMethod.POST}, produces = MEDIATYPE_CHARSET_JSON_UTF8)
    public void get(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //如果为get请求,则为开发者模式验证
        if ("get".equals(request.getMethod().toLowerCase())) {
            doGet();//在开发者模式验证中已处理,在此省略
        } else {
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            PrintWriter out = response.getWriter();
            try {
                Map<String, String> map = MessageUtil.xmlToMap(request);
                String ToUserName = map.get("ToUserName");
                String FromUserName = map.get("FromUserName");
                request.getSession().setAttribute("openid",FromUserName);
                String CreateTime = map.get("CreateTime");
                String MsgType = map.get("MsgType");
                String message = null;
                if (MsgType.equals(WXConstants.MESSAGE_EVENT)) {
                    //从集合中,获取是哪一种事件传入
                    String eventType = map.get("Event");
                    if (eventType.equals(WXConstants.MESSAGE_SUBSCRIBE)) {
                        message = MessageUtil.initNewsMessage(ToUserName, FromUserName);
                    }
                }
                out.print(message); //返回转换后的XML字符串
            } catch (DocumentException e) {
                e.printStackTrace();
            }
            out.close();
        }
    }
}

关注测试号,弹出如下结果:


2017-02-21 10:26:00 weixin_30511039 阅读数 93
  • JavaWeb实战开发

    本课程详细讲解了以下内容:     1.jsp环境搭建及入门、虚拟路径和虚拟主机、JSP执行流程     2.使用Eclipse快速开发JSP、编码问题、JSP页面元素以及request对象、使用request对象实现注册示例     3.请求方式的编码问题、response、请求转发和重定向、cookie、session执行机制、session共享问题      4.session与cookie问题及application、cookie补充说明及四种范围对象作用域      5.JDBC原理及使用Statement访问数据库、使用JDBC切换数据库以及PreparedStatement的使用、Statement与PreparedStatement的区别      6.JDBC调用存储过程和存储函数、JDBC处理大文本CLOB及二进制BLOB类型数据      7.JSP访问数据库、JavaBean(封装数据和封装业务逻辑)      8.MVC模式与Servlet执行流程、Servlet25与Servlet30的使用、ServletAPI详解与源码分析      9.MVC案例、三层架构详解、乱码问题以及三层代码流程解析、完善Service和Dao、完善View、优化用户体验、优化三层(加入接口和DBUtil)     1 0.Web调试及bug修复、分页SQL(Oracle、MySQL、SQLSERVER)      11.分页业务逻辑层和数据访问层Service、Dao、分页表示层Jsp、Servlet      12.文件上传及注意问题、控制文件上传类型和大小、下载、各浏览器下载乱码问题      13.EL表达式语法、点操作符和中括号操作符、EL运算、隐式对象、JSTL基础及set、out、remove      14.过滤器、过滤器通配符、过滤器链、监听器      15.session绑定解绑、钝化活化      16.以及Ajax的各种应用      17. Idea环境下的Java Web开发

    3688 人正在学习 去看看 颜群

用户在关注与取消关注公众号时,微信会把这个事件推送到开发者填写的URL。方便开发者给用户下发欢迎消息或者做帐号的解绑。

微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次

关于重试的消息排重,推荐使用FromUserName + CreateTime 排重。

假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。

 

推送XML数据包示例:

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[subscribe]]></Event>
</xml>

 

 

参数说明:

ToUserName--------开发者微信号

FromUserName-----发送方帐号(一个OpenID)

CreateTime----------消息创建时间 (整型)

MsgType------------消息类型,event

Event----------------事件类型,subscribe(订阅)、unsubscribe(取消订阅)

EventKey------------无

 

 

转为数组时例子:

Array
(
    [ToUserName] => gh_62287cf4ebbf
    [FromUserName] => okuRis8VoZgHXUfIFQKKWhEQmn4I
    [CreateTime] => 1455688386
    [MsgType] => event
    [Event] => subscribe
    [EventKey] => 
)

转载于:https://www.cnblogs.com/jucheng/p/6422838.html

2016-07-12 10:43:17 sinat_29581293 阅读数 1487
  • JavaWeb实战开发

    本课程详细讲解了以下内容:     1.jsp环境搭建及入门、虚拟路径和虚拟主机、JSP执行流程     2.使用Eclipse快速开发JSP、编码问题、JSP页面元素以及request对象、使用request对象实现注册示例     3.请求方式的编码问题、response、请求转发和重定向、cookie、session执行机制、session共享问题      4.session与cookie问题及application、cookie补充说明及四种范围对象作用域      5.JDBC原理及使用Statement访问数据库、使用JDBC切换数据库以及PreparedStatement的使用、Statement与PreparedStatement的区别      6.JDBC调用存储过程和存储函数、JDBC处理大文本CLOB及二进制BLOB类型数据      7.JSP访问数据库、JavaBean(封装数据和封装业务逻辑)      8.MVC模式与Servlet执行流程、Servlet25与Servlet30的使用、ServletAPI详解与源码分析      9.MVC案例、三层架构详解、乱码问题以及三层代码流程解析、完善Service和Dao、完善View、优化用户体验、优化三层(加入接口和DBUtil)     1 0.Web调试及bug修复、分页SQL(Oracle、MySQL、SQLSERVER)      11.分页业务逻辑层和数据访问层Service、Dao、分页表示层Jsp、Servlet      12.文件上传及注意问题、控制文件上传类型和大小、下载、各浏览器下载乱码问题      13.EL表达式语法、点操作符和中括号操作符、EL运算、隐式对象、JSTL基础及set、out、remove      14.过滤器、过滤器通配符、过滤器链、监听器      15.session绑定解绑、钝化活化      16.以及Ajax的各种应用      17. Idea环境下的Java Web开发

    3688 人正在学习 去看看 颜群
最近由于工作需要,接触了微信公众号的开发。业务上要求绑定微信用户和系统用户,以便用户在一次绑定后能够通过系统用户的身份去使用一些功能。我关注的招行信用卡公众号实现了这个功能,所以估计还是可行的,在网上搜索了一下,发现这个问题没什么好的答案,很多都说取不到微信用户名实现不了,甚至有说实现了这个功能的应该是与微信有内部合作的。
搜索无果,遂自己动手实验,后发现其实完全可以的,看来实践才是检验真理的唯一标准,方案上也很简单,我分几点来说。
 
用OpenID绑定即可
微信接口中虽然没给用户的微信账号,但给了用户的OpenID,这个OpenID对一个公众号是唯一的,测试也证明不会改变,也就是说同一个微信号和同一个公众号交互,我们得到的OpenID是不会变的,因此,可以用OpenID作为微信用户的身份标识。
如何绑定
俗话说,没吃过猪肉还没见过猪跑。看招行信用卡公众号是如何做的,在微信里面给用户一个验证链接,用户点击链接,微信会用内嵌的浏览器打开这个链接,然后就是一般的网页登录验证界面,我们通过HTTP(S)获取用户输入的系统用户名与密码,验证通过后完成绑定。 具体如何生成链接和如何传递OpenID下面详述。
如何生成绑定链接
绑定涉及到用户的身份甚至利益,所以需要注意安全性。我们需要绑定的是OpenID和系统用户,系统用户名是用户直接在链接页面输入后通过HTTP(S)传给我们的,这没有问题。OpenID对用户来说透明,用户不会传给我们,我们也只有在用户在微信中向公众号发消息时才可获得OpenID,所以很明显,OpenID需要包含在生成的链接中,至于需不需要对OpenID作加密就看你自己了,我觉得这不重要,更为重要的是要在链接中带上签名和加上时间戳。因为我们需要确认这个链接是由我们服务端生成的,用户自己或者其他人不能够伪造出这个链接,加上时间戳是为了给这个链接一个过期时间,如果不限制过期时间,假设用户绑定后这个链接通过某种方式被别人知道,那么这个人就可以把自己的账号与用户的微信号绑定。所以我采取的方法是用OpenID、过期时间再加上一个密钥生成签名,生成签名的方法和微信服务器接口验证时的签名方法类似(密钥最好另选一个只有自己知道的)。
如何传递OpenID
有了绑定链接,用户点了绑定链接,但这只是第一步,第二步我们需要在用户在链接页面提交登录请求后进行验证,OpenID怎么传到第二步中呢?有人说了,这还不简单,在登录表单中加一个隐藏域放用户的OpenID一起提交给验证的Handler不就OK了,那我只能说很遗憾,你前面所做的安全工作都白费了,一旦A用户的OpenID泄漏,B用户就可以把自己的账号与A用户的微信号绑定了。所以永远不要相信客户端提交的东西。我的方法是当用户点击生成链接后,在链接页载入时,将OpenID存到session中,因为这个session是没法伪造的(cookie被盗除外),所以只有点击这个链接的用户的session中才会有链接中包含的OpenID。
关于微信服务器签名多说一句
大家都知道微信公众号消息接口验证时微信会向我们服务器发一个GET请求,在其中带上只有我们和微信服务器知道的签名,我们在请求处理Handler中会验证这个签名,这点大家无异议;消息接口验证通过后,微信就会把用户发的消息以POST的方式发给我们,很多人可能会在这里忽视对签名的检查,从而给恶意者伪造用户请求的机会。在微信以POST方式传递用户的消息时,仍然会将签名信息附在URL参数中,我们在处理每一个POST请求时,第一步还是得像处理消息接口验证时一样,去对URL参数中的签名作验证,只有签名验证通过后才可去取POST的信息。
绑定流程的详细描述
我在上面说了基本方法,但不够详细,导致一些新手朋友还是不清楚具体如何操作,所以我在此尝试更加详细地描述整个过程的每一步:
数据库中建立用户OpenID和系统用户的绑定关系表,初始时为空。
 
用户和微信交互时,你可以取到用户的OpenID。
 
检查数据表,如发现该OpenID没有绑定系统用户,则返回一个链接供用户在微信内嵌浏览器中打开,这个链接打开后类似于系统用户登录界面。
 
关键是链接的生成,链接需要带3个url参数:
 
 1. 用户OpenID:因为你需要在绑定页面中取到是哪个微信用户想要绑定系统用户。
 
 2. 时间戳timestamp:这是为了防止链接泄漏出去被恶意利用,具体来说就是一个你指定的过期时间,超过这个时间这个链接就失效了,用户只能再次获取。
 
 3. 签名signature:这是为了保证此验证链接只有你才可能生成,用户及第三方均无法伪造。
签名的生成需要你有一个只有你知道的token(密钥,不要与设置在公众号里面的token相同),生成签名方法和验证微信服务器消息真实性类似。流程如下:
 
 1. 将token、OpenID、timestamp三个参数进行字典序排序。
 
 2. 将三个参数字符串拼接成一个字符串进行sha1加密,得到链接的signature参数。
用户打开某个绑定链接时,你首先验证链接的有效性,即按上述5.1和5.2中描述的同样的步骤得到signature与参数中的sinature对比,如果相同,则再检查链接是否超时,两步验证均通过,你就可以将用户的微信OpenID设置到用户的session中,然后你就可以渲染验证页面,让用户输入其系统用户名和密码以提交给你服务器进行验证。
 
在用户提交绑定验证请求后,你只需要检查session中有没有你设置的OpenID,没有自然无效,有的话就是要绑定的OpenID了,此时你可以把这个OpenID从session中删除了。然后你如果验证系统用户名和密码通过后,就把这个OpenID和系统用户绑定起来,加入到第1步中说的绑定关系表中。
转自:http://www.2cto.com/weixin/201503/383877.html
 

微信开发者文档

阅读数 1

没有更多推荐了,返回首页