问题描述:
用ssm框架整合shiro管理系统,然后想实现第三方登录功能,比如(qq,微信等),但是遇到了一个棘手的问题,用第三方登录,我们怎么去实现对用户的授权,这个问题困扰了我很久,网上找了很多相关的资料,都没有一个很好答案,然后自己摸索了许久,终于搞定了,所以想很你们分享一哈,哈哈哈。(如果密码不用md5不可逆加密,那就非常好实现了)
效果演示:
我们看一下后台具体情况:
然后我们可以拿到QQ用户信息,将需要的信息保存到我们系统的数据库中,我们可以根据openid来判断该用户信息是否完整,如果openid为空,说明该用户是第一次登陆,我们要让用户完善信息,反之,让用户登录。
那问题来了,我该怎么在ssm+shiro框架中进行修改,才能用第三方登录成功通过shiro认证,并实现登录
1.重写HashedCredentialsMatcher(spring-shiro.xml)
package com.demo.core.shiro;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
/**
* @Author: cxx
* @Date: 2018/3/14 11:30
*/
public class CybHashedCredentialsMatcher extends HashedCredentialsMatcher {
@Override
public boolean doCredentialsMatch(AuthenticationToken authcToken, AuthenticationInfo info) {
UsernamePasswordLoginTypeToken token = (UsernamePasswordLoginTypeToken) authcToken;
// UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
Object accountCredentials = getCredentials(info);
String pwd = String.valueOf(token.getPassword());
System.out.println("*************密码"+pwd+":::"+pwd.length());
System.out.println("accountCredentials:"+accountCredentials);
if(pwd.length() == 32){
System.out.println("进来了,对加密密码进行比较");
return true;
//return equals(pwd, accountCredentials);
}
//将密码加密与系统加密后的密码校验,内容一致就返回true,不一致就返回false
return super.doCredentialsMatch(token, info) ;
}
}
2.重写UsernamePasswordTokenpackage com.demo.core.shiro;
import org.apache.shiro.authc.UsernamePasswordToken;
public class UsernamePasswordLoginTypeToken extends UsernamePasswordToken {
public UsernamePasswordLoginTypeToken(){
super();
}
public String getUphoneNum() {
return uphoneNum;
}
public void setUphoneNum(String uphoneNum) {
this.uphoneNum = uphoneNum;
}
public String getLoginType() {
return loginType;
}
public void setLoginType(String loginType) {
this.loginType = loginType;
}
public String getUtoken() {
return utoken;
}
public void setUtoken(String utoken) {
this.utoken = utoken;
}
private String loginType = "0";// 0为用户密码登录,1为第三方登录登录
private String utoken;
private String uphoneNum;
public UsernamePasswordLoginTypeToken(final String username, final String password,
final boolean rememberMe, String loginType, String utoken) {
super(username, password, rememberMe);
this.loginType = loginType;
this.utoken = utoken;
this.uphoneNum = uphoneNum;
}
}
我们判断是那种登录的时候,我们只需要改变loginType的值就ok了。
用户名和密码:
@RequestMapping(value = "/login",method = RequestMethod.POST,produces = "text/html;charset=UTF-8")
@ResponseBody
public String CheckLogin(HttpServletRequest request, HttpServletResponse response) {
String username = request.getParameter("username");
String password = request.getParameter("password");
String remberme = request.getParameter("remberme");
Boolean isRemberme=false;
if (!StringUtils.isBlank(remberme)){
isRemberme=true;
//记住用户
BASE64Encoder base64Encoder = new BASE64Encoder();
Cookie nameCookie = new Cookie("name",username);
Cookie pwdCookie = new Cookie("pwd",base64Encoder.encode(password.getBytes()));
//3天
nameCookie.setMaxAge(3*24*60*60);
pwdCookie.setMaxAge(3*24*60*60);
response.addCookie(nameCookie);
response.addCookie(pwdCookie);
}else{//清除cookie
Cookie[] cookies = request.getCookies();
for(Cookie cookie:cookies ){
if (cookie.getName().equals("name")||cookie.getName().equals("pwd")) {
cookie.setValue(null);
cookie.setMaxAge(0);// 立即销毁cookie
System.out.println("被删除的cookie名字为:" + cookie.getName());
response.addCookie(cookie);
}
}
}
Subject currentUser = SecurityUtils.getSubject();
HttpSession session = request.getSession();
session.setAttribute("username",username);
AjaxJson ajaxJson = new AjaxJson();
ajaxJson.setRet(200);
ajaxJson.setMsg("登录成功");
//UsernamePasswordToken token =new UsernamePasswordToken(username,password);
UsernamePasswordLoginTypeToken token = new UsernamePasswordLoginTypeToken(username,password,true,"0",password);
try{
if(!currentUser.isAuthenticated()){
System.out.println("验证角色和权限");
token.setRememberMe(isRemberme);
currentUser.login(token);//验证角色和权限
ajaxJson.setRet(200);
ajaxJson.setMsg("登录成功");
}
}catch(UnknownAccountException e){
System.out.println(e.getMessage());
ajaxJson.setRet(400);
ajaxJson.setMsg(e.getMessage());
}catch (LockedAccountException e){
System.out.println(e.getMessage());
ajaxJson.setRet(400);
ajaxJson.setMsg(e.getMessage());
}catch(IncorrectCredentialsException e){
//用户名/密码错误
System.out.println(e.getMessage());
ajaxJson.setRet(400);
ajaxJson.setMsg("用户密码错误,请重试");
}catch (AuthenticationException e) {
String emsg = "其他异常:"+e.getMessage();
System.out.println(emsg);
ajaxJson.setRet(400);
ajaxJson.setMsg("服务器开小差了");
}
return JSONObject.toJSONString(ajaxJson);
}
QQ扫码登录:
@RequestMapping(value = "/afterQQlogin",method = RequestMethod.GET)
public String QQsuccess(HttpServletRequest request, HttpServletResponse response){
response.setContentType("text/html;charset=utf-8");
try {
AccessToken accessTokenObj = (new Oauth()).getAccessTokenByRequest(request);
String accessToken = null, openID = null;
long tokenExpireIn = 0L;
if (accessTokenObj.getAccessToken().equals("")) {
System.out.println("没有获取到响应参数");
try {
response.sendRedirect("QQlogin");
} catch (IOException e) {
e.printStackTrace();
}
}else{
accessToken = accessTokenObj.getAccessToken();
tokenExpireIn = accessTokenObj.getExpireIn();
// 利用获取到的accessToken 去获取当前用的openid -------- start
OpenID openIDObj = new OpenID(accessToken);
openID = openIDObj.getUserOpenID();
List users = userService.findByqqOpenId(openID);
String touser = users.get(0).getUsername();
String topwd = users.get(0).getPassword();
if (users.size()>0){
System.out.println("直接登录"+users.get(0).getUsername()+topwd);
UsernamePasswordLoginTypeToken token = new UsernamePasswordLoginTypeToken(touser,topwd,false,"1",topwd);
HttpSession session = request.getSession();
session.setAttribute("username",users.get(0).getUsername());
Subject currentUser = SecurityUtils.getSubject();
if(!currentUser.isAuthenticated()) {
System.out.println("验证角色和权限");
currentUser.login(token);//验证角色和权限
}
System.out.println("admin/index----->");
return "redirect:/admin/index";
}
System.out.println("openid:" + openID);
request.getSession().setAttribute("qqOpenid", openID);
// 利用获取到的accessToken 去获取当前用户的openid --------- end
UserInfo qzoneUserInfo = new UserInfo(accessToken, openID);
UserInfoBean userInfoBean = qzoneUserInfo.getUserInfo();
if (userInfoBean.getRet() == 0) {
System.out.println(userInfoBean.getNickname());
System.out.println("
");
} else {
System.out.println("很抱歉,没能正确获取到您的信息,原因是: " + userInfoBean.getMsg());
}
}
} catch (QQConnectException e) {
e.printStackTrace();
}
return "modules/qqLogin/index";
}