shiro实现手机验证码登录(涉及到:自定义token、多realm配置、自定义ModularRealmAuthenticator)
2018-01-31 21:10
441 查看
shiro框架提供了一个UsernamePasswordToken令牌,用来验证用户名和密码类的登录。那如果想要通过替他方式登录认证,例如通过手机验证码接口,就需要通过自定义token、自定义realm等来实现。
1、首先,自定义一个token继承UsernamePasswordToken,为什么要继承这个类而不是AuthenticationToken?,是因为这样做保证了用户名密码认证方式任然能正常使用。代码如下。
2、自定义一个ModularRealmAuthenticator的子类,重写doAuthenticate方法,这个方法的功能是用来决定单realm或者多realm时应该怎么做的,代码如下:
authcInfo = new SimpleAuthenticationInfo(exUser.getTEL(), "ok", "xx");这个语句中SimpleAuthenticationInfo的第二个参数设为和自定义token中返回的一样。
4、控制器代码如下:
5、多realm的配置,shiro的其他配置就不贴了,网上很多的。在securityManager配置属性authenticator为自定义的MyModularRealmAuthenicator类,配置如下:
1、首先,自定义一个token继承UsernamePasswordToken,为什么要继承这个类而不是AuthenticationToken?,是因为这样做保证了用户名密码认证方式任然能正常使用。代码如下。
package com.java.travel.token; import java.io.Serializable; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.UsernamePasswordToken; public class UserNamePasswordTelphoneToken extends UsernamePasswordToken implements Serializable { /** * */ private static final long serialVersionUID = 4812793519945855483L; // 手机号码 private String telphoneNum; /** * 重写getPrincipal方法 */ public Object getPrincipal() { // TODO Auto-generated method stub // 如果获取到用户名,则返回用户名,否则返回电话号码 if (telphoneNum == null) { return getUsername(); } else { return getTelphoneNum(); } } /** * 重写getCredentials方法 */ public Object getCredentials() { // TODO Auto-generated method stub // 如果获取到密码,则返回密码,否则返回null if (telphoneNum == null) { return getPassword(); } else { return "ok"; } } public UserNamePasswordTelphoneToken() { // TODO Auto-generated constructor stub } public UserNamePasswordTelphoneToken(final String telphoneNum) { // TODO Auto-generated constructor stub this.telphoneNum = telphoneNum; } public UserNamePasswordTelphoneToken(final String userName, final String password) { // TODO Auto-generated constructor stub super(userName, password); } public String getTelphoneNum() { return telphoneNum; } public void setTelphoneNum(String telphoneNum) { this.telphoneNum = telphoneNum; } public static long getSerialversionuid() { return serialVersionUID; } @Override public String toString() { return "TelphoneToken [telphoneNum=" + telphoneNum + "]"; } }重写了getPrincipal方法和getCredentials方法,getPrincipal方法如果是用用户名和密码方式登录的则就返回用户名,手机验证码登录则表示手机号码,同理getCredentials在用户名密码登录中表示密码,在验证码登录中则什么都不表示,返回一个任意的字符串就可以了,不能返回null,否则认证不会通过的。
2、自定义一个ModularRealmAuthenticator的子类,重写doAuthenticate方法,这个方法的功能是用来决定单realm或者多realm时应该怎么做的,代码如下:
package com.java.travel.ModularRealmAuthenticator; import java.util.Collection; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.pam.ModularRealmAuthenticator; import org.apache.shiro.realm.Realm; import com.java.travel.token.UserNamePasswordTelphoneToken; public class MyModularRealmAuthenticator extends ModularRealmAuthenticator { @Override protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException { // TODO Auto-generated method stub // 判断getRealms()是否返回为空 assertRealmsConfigured(); // 强制转换回自定义的CustomizedToken UserNamePasswordTelphoneToken telphoneToken = (UserNamePasswordTelphoneToken) authenticationToken; // 所有Realm Collection<Realm> realms = getRealms(); // 判断是单Realm还是多Realm if (realms.size() == 1) return doSingleRealmAuthentication(realms.iterator().next(), telphoneToken); else return doMultiRealmAuthentication(realms, telphoneToken); } }3、自定义realm,继承于AuthorizingRealm类,重写doGetAuthorizationInfo和doGetAuthenticationInfo这两个方法,前者是用来做授权处理的,后者用来身份认证。代码如下:
package com.java.travel.realm; import javax.annotation.Resource; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import com.java.travel.entity.ExUser; import com.java.travel.service.ExUserService; public class TelphoneRealm extends AuthorizingRealm{ @Resource ExUserService exUserService; @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // TODO Auto-generated method stub return null; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { // TODO Auto-generated method stub String telphoneNum = (String) token.getPrincipal(); ExUser exUser = exUserService.selectByTelphoneNum(telphoneNum); if (exUser != null) { AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(exUser.getTEL(), "ok", "xx"); return authcInfo; } else { return null; } } }这里要注意AuthenticationInfo
authcInfo = new SimpleAuthenticationInfo(exUser.getTEL(), "ok", "xx");这个语句中SimpleAuthenticationInfo的第二个参数设为和自定义token中返回的一样。
4、控制器代码如下:
/** * 短信验证码登录 * @param telphoneNum * @return */ @RequestMapping(value = "codeLogin", method = RequestMethod.GET) @ResponseBody public int codeLogin(String telphoneNum) { Subject subject = SecurityUtils.getSubject(); UserNamePasswordTelphoneToken token = new UserNamePasswordTelphoneToken(telphoneNum); try { subject.login(token); return 1; } catch (Exception e) { return -1; } }
5、多realm的配置,shiro的其他配置就不贴了,网上很多的。在securityManager配置属性authenticator为自定义的MyModularRealmAuthenicator类,配置如下:
<!-- shiro的配置 --> <!-- 自定义Realm --> <bean id="userNamePasswordRealm" class="com.java.travel.realm.UserNamePasswordRealm" /> <bean id="telphoneRealm" class="com.java.travel.realm.TelphoneRealm" /> <!-- 安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <!-- 单realm的配置 --> <!-- <property name="realm" ref="myRealm" /> --> <!-- 多realm的配置 --> <property name="authenticator" ref="myModularRealmAuthenticator"></property> <property name="realms"> <list> <ref bean="userNamePasswordRealm" /> <ref bean="telphoneRealm" /> </list> </property> </bean> <!-- 配置多个realm的时候如何认证 --> <bean id="myModularRealmAuthenticator" class="com.java.travel.ModularRealmAuthenticator.MyModularRealmAuthenticator"> <property name="authenticationStrategy"> <!-- 认证策略 --> <!-- <bean class="org.apache.shiro.authc.pam.AllSuccessfulStrategy"></bean> --> <bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean> </property> </bean>还需要注意的一点是,在配置认证策略时要结合你的功能配置,我就是由于没注意到这点,吃了个大亏,集中策略如下图所示:
相关文章推荐
- 自定义shiro的Realm实现和CredentialsMatcher实现以及Token实现
- 使用shiro进行登录校验;自定义realm的实现
- 单realm实现shiro手机验证码登录
- 网站登录密码忘记后,通过向手机发送验证码实现找回密码的实现方法
- 使用Spring配置shiro时,自定义Realm中属性无法使用注解注入解决办法
- Java中SSM+Shiro系统登录验证码的实现方法
- Angular获取手机验证码实现移动端登录注册功能
- shiro授权,自定义realm实现授权,shiro与项目集成,在项目中实现认证及授权
- Shiro Review——自定义Realm实现认证
- shiro 配置都正确,不能进入自定义realm
- shiro- session,自定义FormAuthenticationFilter(表单认证器)-->实现验证码校验
- jfinal使用shiro实现登录功能,及Realm的使用
- 使用shiro的的表单过滤器重写shiro默认的认证规则来实现先验证验证码再验证登录所遇到的问题
- Shiro在web应用中实现验证码、回显登录失败信息
- shiro自定义Realm实现
- cc_美团项目user模块之用手机验证码直接登录实现
- SSM+Shiro系统登录验证码的实现
- 使用Spring配置shiro时,自定义Realm中属性无法使用注解注入解决办法
- shiro中自定义realm实现md5散列算法加密的模拟(二)
- cas+tomcat+shiro实现单点登录-3-CAS服务器深入配置(连接MYSQL)