微信免登陆调用静默授权snsapi_base获取open_id
前提:微信用户已经绑定公众号后台系统。
实现思路:根据用户绑定系统后台的账号密码进行免登陆。用户点击登录系统是先做一个授权回调动作;这里需要涉及一个叫授权回调;之前一直没有研究过这个回调;其实它主要的作用是验证后台是否存在一个文件这里的文件可在后台看到,方法就是在服务里添加这个.txt文件就好。路径后面跟回调时用到的路径是一样的。
设置后后我们开始做回调的类
@Path("WxCodeServlet")
public class WxCodeServletController{
@Get
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
@Post
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
request.setCharacterEncoding("UTF-8");
//这里要将你的授权回调地址处理一下,否则微信识别不了
String redirect_uri=URLEncoder.encode("/*你的授权回调地址*/", "UTF-8");
//简单获取openid的话参数response_type与scope与state参数固定写死即可
StringBuffer url=new StringBuffer("https://open.weixin.qq.com/connect/oauth2/authorize?redirect_uri="+redirect_uri+
"&appid="+/*你的appid*/+"&response_type=code&scope=snsapi_base&state=1#wechat_redirect");
response.sendRedirect(url.toString());//这里请不要使用get请求单纯的将页面跳转到该url即可
}
}
上面的回调地址写一下类的路径
@Get
public Object doGet(Invocation inv, HttpServletRequest request, HttpServletResponse response) throws Exception {
try {
log.info("OAuthController---------------");
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
// 用户同意授权后,能获取到code
String code = request.getParameter("code");
String state = request.getParameter("state");
// log.info("code="+code+"&state="+state);
WxSet wxSet = wxSetService.queryAllWxSet().get(0);
String appid = wxSet.getAppId();
String appSecret = wxSet.getAppSecret();
if (!"authdeny".equals(code)) {
// 获取网页授权access_token和openid getOauth2AccessToken
WeixinOauth2Token weixinOauth2Token = AdvancedUtil.getOauth2AccessToken(appid, appSecret, code);
// 网页授权接口访问凭证
String accessToken = weixinOauth2Token.getAccess_token();
// 用户标识
String openId = weixinOauth2Token.getOpenid();
// 根据openid和用户表的绑定关系,确定该微信账号是否可以登录系统,
// 若可登录系统,跳转到系统首页页面,若无权限登录,跳转到登录页面
WxUser wxUser = wxUserService.queryByOpenId(openId);
if(wxUser != null && !StringUtil.isEmpty(wxUser.getLoginName()) && "1".equals(wxUser.getState()+"")){
// 该微信绑定过系统用户,进行初始化用户数据,跳转进入系统首页
User userInfo = userManagerDAO.selectUser(wxUser.getLoginName());
if (userInfo!=null && !StringUtil.isEmpty(userInfo.getLoginId()) && !StringUtil.isEmpty(userInfo.getPassword())) {//用户表中存在该用户
String username = userInfo.getLoginId();
String password = userInfo.getPassword();
password = MD5.getMD5(password.getBytes());
String nonce = null;
String oapassword = null;
String oatoken = null;
if(oatoken !=null){//OA APP切换 单点登录
if(checkoa(oatoken)){
CodeUtil cu = new CodeUtil();
nonce = cu.md5Encode(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:S").format(new Date())+UUID.randomUUID().toString());
HttpDigest digest = new HttpDigest();
digest.setUsername(username);
digest.setNonce(nonce);
User user = permissionService.checkLogin(username);
if(user.getLoginPrivilege()==0){
log.info(username+"|快捷登录|无权限");
return "../indexWeChat";
}
digest.setMsg("登录成功");
digest.setUser(permissionService.initUserSession(user, null));
permissionService.insertLoginInfo(inv,user,inv.getRequest().getHeader("User-Agent"),digest.getNonce(),2);//登录日志
Accessor accessor = new Accessor();
accessor.nonce = digest.getNonce();
accessor.ipnonce = MD5.getMD5((digest.getNonce()+":"+SystemUtil.getIpAddr(inv.getRequest())).getBytes());
accessor.username = digest.getUsername();
accessor.userId = user.getUserId();
accessor.timestamp = System.currentTimeMillis();
user.setToken(digest.getNonce());
AuthProvider.setAccessToken(accessor,user);
Map <String,String>map = new HashMap<String,String>();
map.put("userName", user.getUserName());
map.put("departmentOrganizationName", user.getDepartmentOrganizationName());
map.put("userId", Long.toString(user.getUserId()));
map.put("isAdmin", user.getIsAdmin());
map.put("nonce",nonce);
map.put("departId",String.valueOf(digest.getUser().getDepartmentOrganizationId()));
CookieUtil.addCookie(inv.getRequest(), inv.getResponse(), false,
digest.getUsername(),"username", null,null);
CookieUtil.addCookie(inv.getRequest(), inv.getResponse(), false,
digest.getNonce(),"nonce", null,null);
log.info(username+"|快捷登录|成功");
return "../indexWeChat";
}
log.info(username+"|快捷登录|失败,"+oatoken);
return "../loginWeChat";
}else if (username!=null) {//普通登录
boolean flag = false;
HttpDigest digest = new HttpDigest();
digest.setUsername(username);
digest.setNonce(nonce);
if(1==utilsService.getLoginLevel()){//本地登录验证
flag =validate(digest,password);
}else if(2==utilsService.getLoginLevel()){//oa账号验证
if(loginoa(username, oapassword)){
User user = permissionService.checkLogin(digest.getUsername());
digest.setUser(user);
if(user !=null){
if(user.getLoginPrivilege()!=0){
digest.setMsg("登录成功");
digest.setUser(permissionService.initUserSession(user, null));
flag =true;
}else{
digest.setMsg("您无权限登录!");
log.info(username+"|oa单点登录|无权限");
}
}else{
digest.setMsg("用户名不存在!");
log.info(username+"|oa单点登录|用户名不存在");
}
}else{
digest.setMsg("oa认证失败!");
log.info(username+"|oa单点登录|认证失败");
}
}
if(flag){
if(digest.getNonce()==null || "null".equals(digest.getNonce())){
CodeUtil cu = new CodeUtil();
nonce = cu.md5Encode(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:S").format(new Date())+UUID.randomUUID().toString());
digest.setNonce(nonce);
}
User user = digest.getUser();
inv.addModel("i_sys", 3);
permissionService.insertLoginInfo(inv,user,inv.getRequest().getHeader("User-Agent"),digest.getNonce(),2);//登录日志
Accessor accessor = new Accessor();
accessor.nonce = digest.getNonce();
accessor.ipnonce = MD5.getMD5((digest.getNonce()+":"+SystemUtil.getIpAddr(inv.getRequest())).getBytes());
accessor.username = digest.getUsername();
accessor.userId = user.getUserId();
accessor.timestamp = System.currentTimeMillis();
user.setToken(digest.getNonce());
AuthProvider.setAccessToken(accessor,user);
Map <String,String>map = new HashMap<String,String>();
map.put("userName", user.getUserName());
map.put("departmentOrganizationName", user.getDepartmentOrganizationName());
map.put("userId", Long.toString(user.getUserId()));
map.put("isAdmin", user.getIsAdmin());
map.put("nonce",digest.getNonce());
map.put("departId",String.valueOf(digest.getUser().getDepartmentOrganizationId()));
CookieUtil.addCookie(inv.getRequest(), inv.getResponse(), false,
digest.getUsername(),"username", null,null);
CookieUtil.addCookie(inv.getRequest(), inv.getResponse(), false,
digest.getNonce(),"nonce", null,null);
log.info(username+"|oa单点登录|成功");
return "../indexWeChat";
}
return "../loginWeChat";
}
return "../loginWeChat";
} else {
return "../loginWeChat";
}
} else{
// 该微信未绑定过系统用户,跳转页面到登录页面
//System.out.println("该微信未绑定过系统用户,跳转页面到登录页面");
com.lzzj.platform.domain.system.User u = this.permissionService
.getLoginUser();
Map<String, String> authParam = SystemUtil.getAuth(InvocationUtils
.getCurrentThreadRequest());
if (u == null || !u.getToken().equals(authParam.get("nonce"))) {
return "../loginWeChat";
} else{
return "../indexWeChat";
}
}
} else{
return "../loginWeChat";
}
} catch (Exception e) {
log.info("OAuthController--------1111-------", e);
return "../loginWeChat";
}
}
标红的地方触发的方法:
/**
* 获取网页授权凭证
*
* @param appId 公众账号的唯一标识
* @param appSecret 公众账号的**
* @param code
* @return WeixinAouth2Token
*/
public static WeixinOauth2Token getOauth2AccessToken(String appId, String appSecret, String code) {
WeixinOauth2Token wat = null;
// 拼接请求地址
String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
requestUrl = requestUrl.replace("APPID", appId);
requestUrl = requestUrl.replace("SECRET", appSecret);
requestUrl = requestUrl.replace("CODE", code);
// 获取网页授权凭证
String respStr = CommonUtil.httpsRequest(requestUrl, "GET", null);
log.info("获取网页授权凭证="+respStr);
wat = JSONObject.parseObject(respStr, WeixinOauth2Token.class);
return wat;
}
/**
* 通过网页授权获取用户信息
*
* @param accessToken 网页授权接口调用凭证
* @param openId 用户标识
* @return SNSUserInfo
*/
@SuppressWarnings( { "deprecation", "unchecked" })
public static SNSUserInfo getSNSUserInfo(String accessToken, String openId) {
SNSUserInfo snsUserInfo = null;
// 拼接请求地址
String requestUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);
// 通过网页授权获取用户信息
String respStr = CommonUtil.httpsRequest(requestUrl, "GET", null);
log.info("通过网页授权获取用户信息="+respStr);
snsUserInfo = JSONObject.parseObject(respStr, SNSUserInfo.class);
return snsUserInfo;
}
}
表红的地方触发方法:
public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
String respStr = null;
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 设置请求方式(GET/POST)
conn.setRequestMethod(requestMethod);
// 当outputStr不为null时向输出流写数据
if (null != outputStr) {
OutputStream outputStream = conn.getOutputStream();
// 注意编码格式
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 从输入流读取返回内容
InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 释放资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
conn.disconnect();
respStr = buffer.toString();
} catch (ConnectException ce) {
log.error("连接超时:{}", ce);
} catch (Exception e) {
log.error("https请求异常:{}", e);
}
return respStr;
}
/**
* 方法名:main</br>
* 详述:生成URL编码 </br>
* 开发人员:souvc </br>
* 创建时间:2016-1-4 </br>
* @param args 说明返回值含义
* @throws 说明发生此异常的条件
*/
public static void main(String[] args) {
String source="192.168.0.129";
System.out.println(CommonUtil.urlEncodeUTF8(source));
}
/**
* 根据map,获得json字符串
* @param map
* @return
*/
public static String getJsonStr(Map<String, Object> map){
return JSONObject.toJSONString(map);
}
public static <T> boolean isNullList(List<T> list) {
if (list == null || list.size() == 0) {
return true;
}
return false;
}
public static boolean isNullString(String str) {
if (str == null || str.trim().length() == 0) {
return true;
}
return false;
}
public static boolean isNullString(String... strs) {
for (String s : strs) {
if (isNullString(s)) {
return true;
}
}
return false;
}
public static String bytesToHexString(byte[] src){
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
/**
* Convert hex string to byte[]
* @param hexString the hex string
* @return byte[]
*/
public static byte[] hexStringToBytes(String hexString) {
if (hexString == null || hexString.equals("")) {
return null;
}
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] d = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return d;
}
/**
* Convert char to byte
* @param c char
* @return byte
*/
public static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
}
到这里基本已经实现回调。