1
0
xiongzhu 7 лет назад
Родитель
Сommit
68fcc9a66d

+ 2 - 0
src/main/java/com/izouma/awesomeadmin/service/UserInfoService.java

@@ -4,6 +4,7 @@ import java.util.List;
 
 import com.izouma.awesomeadmin.dto.Page;
 import com.izouma.awesomeadmin.model.UserInfo;
+import com.izouma.awesomeadmin.service.impl.UserInfoServiceImpl;
 
 /**
  * user_info service接口类
@@ -27,5 +28,6 @@ public interface UserInfoService {
 
     UserInfo login(String username, String password);
 
+    UserInfo loginSms(String phone, String code, String sessionId) throws UserInfoServiceImpl.LoginException;
 }
 

+ 42 - 0
src/main/java/com/izouma/awesomeadmin/service/impl/UserInfoServiceImpl.java

@@ -7,6 +7,9 @@ import java.util.Map;
 import com.izouma.awesomeadmin.constant.AppConstant;
 import com.izouma.awesomeadmin.dto.Page;
 import com.izouma.awesomeadmin.util.MD5Util;
+import com.izouma.awesomeadmin.util.PropertiesFileLoader;
+import io.rong.RongCloud;
+import io.rong.models.SMSVerifyCodeResult;
 import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -24,6 +27,8 @@ import com.izouma.awesomeadmin.service.UserInfoService;
 public class UserInfoServiceImpl implements UserInfoService {
 
     private static Logger logger = Logger.getLogger(UserInfoServiceImpl.class);
+    private RongCloud rongCloud = RongCloud.getInstance(PropertiesFileLoader.getProperties("rongyunappkey"), PropertiesFileLoader.getProperties("rongyunappsecret"));
+
 
     @Autowired
     private UserInfoMapper userInfoMapper;
@@ -159,5 +164,42 @@ public class UserInfoServiceImpl implements UserInfoService {
         return null;
     }
 
+    @Override
+    public UserInfo loginSms(String phone, String code, String sessionId) throws LoginException {
+        logger.info("loginSms");
+        SMSVerifyCodeResult sMSVerifyCodeResult;
+        try {
+            sMSVerifyCodeResult = rongCloud.sms.verifyCode(sessionId, code);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new LoginException("验证码错误");
+        }
+        if (200 == sMSVerifyCodeResult.getCode()) {
+            Boolean success = sMSVerifyCodeResult.getSuccess();
+            if (success) {
+                UserInfo userInfo = new UserInfo();
+                userInfo.setPhone(phone);
+                userInfo = getUserInfo(userInfo);
+                if (userInfo == null) {
+                    userInfo = new UserInfo();
+                    userInfo.setPhone(phone);
+                    userInfo.setUsername(phone);
+                    userInfo.setNickname(phone);
+                    userInfo.setIcon("https://microball.oss-cn-hangzhou.aliyuncs.com/huanbaojia/icon_morentouxiang.png");
+                    if (!createUserInfo(userInfo)) {
+                        throw new LoginException("登录失败");
+                    }
+                }
+                return userInfo;
+            }
+        }
+        throw new LoginException("验证码错误");
+    }
+
+    public class LoginException extends Exception {
+        public LoginException(String message) {
+            super(message);
+        }
+    }
 }
 

+ 4 - 24
src/main/java/com/izouma/awesomeadmin/shiro/Bos_realm.java → src/main/java/com/izouma/awesomeadmin/shiro/BaseRealm.java

@@ -5,21 +5,20 @@ import com.izouma.awesomeadmin.model.UserInfo;
 import com.izouma.awesomeadmin.service.SysRoleService;
 import com.izouma.awesomeadmin.service.UserInfoService;
 import org.apache.log4j.Logger;
-import org.apache.shiro.authc.*;
 import org.apache.shiro.authz.AuthorizationInfo;
 import org.apache.shiro.authz.SimpleAuthorizationInfo;
 import org.apache.shiro.realm.AuthorizingRealm;
 import org.apache.shiro.subject.PrincipalCollection;
 import org.springframework.beans.factory.annotation.Autowired;
 
-public class Bos_realm extends AuthorizingRealm {
-    private static Logger logger = Logger.getLogger(Bos_realm.class);
+public abstract class BaseRealm extends AuthorizingRealm {
+    protected static Logger logger = Logger.getLogger(PhoneCodeRealm.class);
 
     @Autowired
-    private UserInfoService userInfoService;
+    protected UserInfoService userInfoService;
 
     @Autowired
-    private SysRoleService sysRoleService;
+    protected SysRoleService sysRoleService;
 
     //授权
     @Override
@@ -38,23 +37,4 @@ public class Bos_realm extends AuthorizingRealm {
         }
         return info;
     }
-
-    //认证
-    @Override
-    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
-        //获取令牌(里面存放new UsernamePasswordToken放入的账号和密码)
-        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
-
-        UserInfo userInfo = userInfoService.login(userToken.getUsername(), new String(userToken.getPassword()));
-
-        if (userInfo != null) {
-            //参数1.用户认证的对象(subject.getPrincipal();返回的对象),
-            //参数2.从数据库根据用户名查询到的用户的密码
-            //参数3.把当前自定义的realm对象传给SimpleAuthenticationInfo,在配置文件需要注入
-            AuthenticationInfo Info = new SimpleAuthenticationInfo(userInfo, new String(userToken.getPassword()), this.getName());
-            return Info;
-        } else {
-            return null;
-        }
-    }
 }

+ 41 - 0
src/main/java/com/izouma/awesomeadmin/shiro/MyModularRealmAuthenticator.java

@@ -0,0 +1,41 @@
+package com.izouma.awesomeadmin.shiro;
+
+import org.apache.log4j.Logger;
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.pam.AuthenticationStrategy;
+import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
+import org.apache.shiro.realm.Realm;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+public class MyModularRealmAuthenticator extends ModularRealmAuthenticator {
+    protected static Logger logger = Logger.getLogger(MyModularRealmAuthenticator.class);
+
+    protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) {
+        AuthenticationStrategy strategy = this.getAuthenticationStrategy();
+        AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token);
+
+        Iterator var5 = realms.iterator();
+
+        while (var5.hasNext()) {
+            Realm realm = (Realm) var5.next();
+            aggregate = strategy.beforeAttempt(realm, token, aggregate);
+            if (realm.supports(token)) {
+                logger.trace("Attempting to authenticate token [{}] using realm [{}]");
+                AuthenticationInfo info = null;
+                Throwable t = null;
+
+                info = realm.getAuthenticationInfo(token);
+
+                aggregate = strategy.afterAttempt(realm, token, info, aggregate, t);
+            } else {
+                logger.debug("Realm [{}] does not support token {}.  Skipping realm.");
+            }
+        }
+
+        aggregate = strategy.afterAllAttempts(token, aggregate);
+        return aggregate;
+    }
+}

+ 23 - 0
src/main/java/com/izouma/awesomeadmin/shiro/PhoneCodeRealm.java

@@ -0,0 +1,23 @@
+package com.izouma.awesomeadmin.shiro;
+
+import com.izouma.awesomeadmin.model.UserInfo;
+import com.izouma.awesomeadmin.service.impl.UserInfoServiceImpl;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.SimpleAuthenticationInfo;
+
+public class PhoneCodeRealm extends BaseRealm {
+
+    @Override
+    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
+        UserInfo userInfo = null;
+        PhoneCodeToken phoneCodeToken = (PhoneCodeToken) token;
+        try {
+            userInfo = userInfoService.loginSms(phoneCodeToken.getPhone(), phoneCodeToken.getCode(), phoneCodeToken.getSessionId());
+            return new SimpleAuthenticationInfo(userInfo, token.getCredentials(), this.getName());
+        } catch (UserInfoServiceImpl.LoginException e) {
+            throw new AuthenticationException(e.getMessage());
+        }
+    }
+}

+ 71 - 0
src/main/java/com/izouma/awesomeadmin/shiro/PhoneCodeToken.java

@@ -0,0 +1,71 @@
+package com.izouma.awesomeadmin.shiro;
+
+import org.apache.shiro.authc.HostAuthenticationToken;
+import org.apache.shiro.authc.RememberMeAuthenticationToken;
+
+public class PhoneCodeToken implements HostAuthenticationToken, RememberMeAuthenticationToken {
+
+    private boolean rememberMe;
+    private String host;
+    private String phone;
+    private String code;
+    private String sessionId;
+
+    public PhoneCodeToken(String phone, String code, String sessionId) {
+        this.phone = phone;
+        this.code = code;
+        this.sessionId = sessionId;
+    }
+
+    public void setRememberMe(boolean rememberMe) {
+        this.rememberMe = rememberMe;
+    }
+
+    public void setHost(String host) {
+        this.host = host;
+    }
+
+    public String getPhone() {
+        return phone;
+    }
+
+    public void setPhone(String phone) {
+        this.phone = phone;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getSessionId() {
+        return sessionId;
+    }
+
+    public void setSessionId(String sessionId) {
+        this.sessionId = sessionId;
+    }
+
+    @Override
+    public String getHost() {
+        return host;
+    }
+
+    @Override
+    public boolean isRememberMe() {
+        return rememberMe;
+    }
+
+    @Override
+    public Object getPrincipal() {
+        return phone;
+    }
+
+    @Override
+    public Object getCredentials() {
+        return code;
+    }
+}

+ 18 - 0
src/main/java/com/izouma/awesomeadmin/shiro/UserPasswordRealm.java

@@ -0,0 +1,18 @@
+package com.izouma.awesomeadmin.shiro;
+
+import com.izouma.awesomeadmin.model.UserInfo;
+import org.apache.shiro.authc.*;
+
+public class UserPasswordRealm extends BaseRealm {
+
+    @Override
+    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
+        UserInfo userInfo = null;
+        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
+        userInfo = userInfoService.login(userToken.getUsername(), new String(userToken.getPassword()));
+        if (userInfo == null) {
+            throw new AuthenticationException("用户名或密码错误");
+        }
+        return new SimpleAuthenticationInfo(userInfo, token.getCredentials(), this.getName());
+    }
+}

+ 90 - 0
src/main/java/com/izouma/awesomeadmin/web/RongCloudController.java

@@ -0,0 +1,90 @@
+package com.izouma.awesomeadmin.web;
+
+import com.izouma.awesomeadmin.constant.RongConstant;
+import com.izouma.awesomeadmin.dto.Result;
+import com.izouma.awesomeadmin.service.RongYunTokenService;
+import com.izouma.awesomeadmin.util.PropertiesFileLoader;
+import io.rong.RongCloud;
+import io.rong.models.SMSSendCodeResult;
+import io.rong.models.SMSVerifyCodeResult;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.http.HttpServletRequest;
+
+
+@Controller
+@RequestMapping("/rong")
+public class RongCloudController extends BaseController {
+
+    @Autowired
+    private RongYunTokenService rongYunTokenService;
+
+
+    private RongCloud rongCloud = RongCloud.getInstance(PropertiesFileLoader.getProperties("rongyunappkey"), PropertiesFileLoader.getProperties("rongyunappsecret"));
+
+    @RequestMapping(value = "/sendCode", method = RequestMethod.GET)
+    @ResponseBody
+    public Result sendCode(@RequestParam("phone") String mobile, HttpServletRequest request) {
+        try {
+            SMSSendCodeResult smsSendCodeResult = rongCloud.sms.sendCode(mobile, RongConstant.VERIFY_TEMPLATEID, "86", null, null);
+
+            if (200 == smsSendCodeResult.getCode()) {
+
+                String sessionId = smsSendCodeResult.getSessionId();
+
+                return new Result(true, new StringBuilder(sessionId));
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return new Result(false, "发送失败,请稍后重试");
+    }
+
+
+    @RequestMapping(value = "/verifyCode", method = RequestMethod.GET)
+    @ResponseBody
+    public Result verifyCode(@RequestParam("sessionId") String sessionId,
+                             @RequestParam("code") String code) {
+        try {
+            SMSVerifyCodeResult sMSVerifyCodeResult = rongCloud.sms.verifyCode(sessionId, code);
+            if (200 == sMSVerifyCodeResult.getCode()) {
+
+                Boolean success = sMSVerifyCodeResult.getSuccess();
+                if (success) {
+
+                    return new Result(true, null);
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return new Result(false, "验证失败");
+    }
+
+
+    @RequestMapping(value = "/sendNotify", method = RequestMethod.GET)
+    @ResponseBody
+    public Result sendNotify(@RequestParam(required = true, value = "mobile") String mobile) {
+
+        String result;
+        try {
+            SMSSendCodeResult smsSendCodeResult = rongCloud.sms.sendNotify(mobile, RongConstant.NOTIFY_TEMPLATEID, "86", null, null, null);
+            if (200 == smsSendCodeResult.getCode()) {
+
+                String sessionId = smsSendCodeResult.getSessionId();
+                return new Result(true, sessionId);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return new Result(false, "发送失败,请稍后重试");
+    }
+}

+ 26 - 6
src/main/java/com/izouma/awesomeadmin/web/UserInfoController.java

@@ -13,11 +13,13 @@ import com.izouma.awesomeadmin.model.DepartInfo;
 import com.izouma.awesomeadmin.service.DepartInfoService;
 import com.izouma.awesomeadmin.service.PowerInfoService;
 import com.izouma.awesomeadmin.service.SysMenuService;
+import com.izouma.awesomeadmin.shiro.PhoneCodeToken;
 import com.izouma.awesomeadmin.util.CookieUtil;
 import com.izouma.awesomeadmin.util.ExportExcelUtil;
 import org.activiti.engine.IdentityService;
 import org.apache.commons.lang.StringUtils;
 import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authc.AuthenticationException;
 import org.apache.shiro.authc.UsernamePasswordToken;
 import org.apache.shiro.authz.annotation.RequiresAuthentication;
 import org.apache.shiro.subject.Subject;
@@ -44,15 +46,15 @@ import javax.servlet.http.HttpSession;
 public class UserInfoController extends BaseController {
 
     @Autowired
-    private UserInfoService   userInfoService;
+    private UserInfoService userInfoService;
     @Autowired
-    private PowerInfoService  powerInfoService;
+    private PowerInfoService powerInfoService;
     @Autowired
-    private SysMenuService    sysMenuService;
+    private SysMenuService sysMenuService;
     @Autowired
     private DepartInfoService departInfoService;
     @Autowired
-    private IdentityService   identityService;
+    private IdentityService identityService;
 
     /**
      * <p>获取全部记录。</p>
@@ -209,12 +211,30 @@ public class UserInfoController extends BaseController {
                 CookieUtil.addCookie(response, "JSESSIONID", session.getId(), 3 * 24 * 60 * 60);
             }
             return new Result(true, "登录成功");
-        } catch (Exception e) {
-            //认证登录失败抛出异常
+        } catch (AuthenticationException e) {
+            e.printStackTrace();
             return new Result(false, "登录失败");
         }
     }
 
+    @RequestMapping(value = "/loginSms", method = RequestMethod.POST)
+    @ResponseBody
+    public Result loginBySms(@RequestParam("phone") String phone, @RequestParam("code") String code, @RequestParam("sessionId") String sessionId, HttpServletRequest request, HttpServletResponse response) {
+        Subject subject = SecurityUtils.getSubject();
+        PhoneCodeToken phoneCodeToken = new PhoneCodeToken(phone, code, sessionId);
+        try {
+            subject.login(phoneCodeToken);
+        } catch (AuthenticationException e) {
+            e.printStackTrace();
+            return new Result(false, e.getMessage());
+        }
+        UserInfo user = (UserInfo) subject.getPrincipal();
+        identityService.setAuthenticatedUserId(user.getId().toString());
+        HttpSession session = request.getSession();
+        CookieUtil.addCookie(response, "JSESSIONID", session.getId(), 3 * 24 * 60 * 60);
+        return new Result(true, user);
+    }
+
     @RequiresAuthentication
     @RequestMapping(value = "/logout", method = RequestMethod.POST)
     @ResponseBody

+ 21 - 2
src/main/resources/spring/applicationContext.xml

@@ -40,10 +40,29 @@
     <!-- 注册安全管理器 -->
     <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
         <!-- 注入realm到安全管理器进行密码匹配 -->
-        <property name="realm" ref="BosRealm"/>
+        <property name="authenticator" ref="modularRealmAuthenticator"/>
     </bean>
+
+    <bean id="modularRealmAuthenticator" class="com.izouma.awesomeadmin.shiro.MyModularRealmAuthenticator">
+        <property name="authenticationStrategy">
+            <!-- 认证策略 -->
+            <bean class="org.apache.shiro.authc.pam.FirstSuccessfulStrategy"/>
+        </property>
+        <property name="realms">
+            <list>
+                <ref bean="phoneCodeRealm"/>
+                <ref bean="userPasswordRealm"/>
+            </list>
+        </property>
+    </bean>
+
     <!-- 自定义的realm -->
-    <bean id="BosRealm" class="com.izouma.awesomeadmin.shiro.Bos_realm"/>
+    <bean id="phoneCodeRealm" class="com.izouma.awesomeadmin.shiro.PhoneCodeRealm">
+        <property name="authenticationTokenClass" value="com.izouma.awesomeadmin.shiro.PhoneCodeToken"/>
+    </bean>
+    <bean id="userPasswordRealm" class="com.izouma.awesomeadmin.shiro.UserPasswordRealm">
+        <property name="authenticationTokenClass" value="org.apache.shiro.authc.UsernamePasswordToken"/>
+    </bean>
 
 
     <context:component-scan