您的位置:首页 > 编程语言

关于 项目中用到shiro如何通过token鉴权登录,模拟登录,代码直接登录的问题!

2015-09-10 20:52 1126 查看
1.今天遇到了一个棘手的问题,在此写下博客记录下来,用于提醒自己,以及帮助以后会遇到这样的问题的人

shiro框架中如何通过用户名密码在代码中直接登录?

首先在网上找了下,找到了这种方式:

Subject currentUser = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username,password, false,request.getRemoteAddr());
currentUser.login(token);


由于自己的项目中登录时还要判断用户角色所以,用了UsernamePasswordUsertypeToken.java,代码如下

package com.linkage.educloud.ucenter.login.shiro;

import org.apache.shiro.authc.HostAuthenticationToken;
import org.apache.shiro.authc.RememberMeAuthenticationToken;
/**
* 参考org.apache.shiro.authcUsernamePasswordToken,增加了用户类型参数
* @author caihz
* @see org.apache.shiro.authcUsernamePasswordToken
*/
public class UsernamePasswordUsertypeToken implements HostAuthenticationToken, RememberMeAuthenticationToken {
/**
* 用户名
*/
private String username;

/**
* 密码, in char[] format
*/
private char[] password;

/**
* 是否记住我
* 默认值:<code>false</code>
*/
private boolean rememberMe = false;

/**
* 主机名称或ip
*/
private String host;

/**
* 用户类型
*/
private String usertype;

public UsernamePasswordUsertypeToken() {
}

/**
* 构造方法
* @param username 用户名
* @param password 密码(char[])
* @param rememberMe 是否记住我
* @param host 主机或ip
* @param usertype 用户类型
*/
public UsernamePasswordUsertypeToken(final String username, final char[] password,
final boolean rememberMe, final String host, final String usertype) {

this.username = username;
this.password = password;
this.rememberMe = rememberMe;
this.host = host;
this.usertype = usertype;
}

/**
* 构造方法
* @param username 用户名
* @param password 密码(String)
* @param rememberMe 是否记住我
* @param host 主机或ip
* @param usertype 用户类型
*/
public UsernamePasswordUsertypeToken(final String username, final String password,
final boolean rememberMe, final String host, final String usertype) {
this(username, password != null ? password.toCharArray() : null, rememberMe, host, usertype);
}

public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public char[] getPassword() {
return password;
}
public void setPassword(char[] password) {
this.password = password;
}

/**
* Simply returns {@link #getUsername() getUsername()}.
*
* @return the {@link #getUsername() username}.
* @see org.apache.shiro.authc.AuthenticationToken#getPrincipal()
*/
public Object getPrincipal() {
return getUsername();
}

/**
* Returns the {@link #getPassword() password} char array.
*
* @return the {@link #getPassword() password} char array.
* @see org.apache.shiro.authc.AuthenticationToken#getCredentials()
*/
public Object getCredentials() {
return getPassword();
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public boolean isRememberMe() {
return rememberMe;
}
public void setRememberMe(boolean rememberMe) {
this.rememberMe = rememberMe;
}
public String getUsertype() {
return usertype;
}
public void setUsertype(String usertype) {
this.usertype = usertype;
}

/**
* 清除数据
* 密码如果不为空,设置成0x00
*/
public void clear() {
this.username = null;
this.host = null;
this.rememberMe = false;
this.usertype = null;

if (this.password != null) {
for (int i = 0; i < password.length; i++) {
this.password[i] = 0x00;
}
this.password = null;
}

}

/**
* 重写toString方法
*/
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getName());
sb.append(" - ");
sb.append(username);
sb.append(", usertype=").append(usertype);
sb.append(", rememberMe=").append(rememberMe);
if (host != null) {
sb.append(" (").append(host).append(")");
}
return sb.toString();
}

}
将上述代码修改了下,如下:

Subject currentUser = SecurityUtils.getSubject();
UsernamePasswordUsertypeToken token = new UsernamePasswordUsertypeToken(user.getPhone(),user.getLoginPass(), false,req.getRemoteAddr(),role);
currentUser.login(token);


这里controller层里的代码差不多了,接下来要修改shiro里的配置以及Realm

配置如下:

<!-- 和教育的Realm 2015-9-10-->
<bean id="shiroAndEduRealm" class="com.linkage.educloud.ucenter.learn.service.ShiroAndEduRealm">
<!-- property name="accountService" ref="accountService"/ -->
<!-- 获得的用户密码已经是加密过的了,验证的时候不用加密验证了-->
<!-- <property name="credentialsMatcher" ref="credentialsMatcher"/> -->
<property name="authenticationTokenClass" value="com.linkage.educloud.ucenter.login.shiro.UsernamePasswordUsertypeToken"/>
</bean>


<bean id="authenticator" class="com.linkage.educloud.ucenter.login.shiro.FirstSuccessfulModularRealmAuthenticator">
<property name="authenticationStrategy" ref="firstSuccessfulStrategy"/>
<property name="realms">
<list>
<ref bean="shiroDbRealm"/>
<ref bean="shiroXxtRealm"/>
<ref bean="shiroAndEduRealm"/>
</list>
</property>
</bean>


com.linkage.educloud.ucenter.learn.service.ShiroAndEduRealm.java代码如下:

package com.linkage.educloud.ucenter.learn.service;

import org.apache.shiro.authc.AccountException;
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.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.linkage.educloud.api.ucenter.service.Uc2XXTIfaceService;
import com.linkage.educloud.base.util.StringUtil;
import com.linkage.educloud.domain.ucenter.login.UcenterLoginUser;
import com.linkage.educloud.ucenter.login.service.UcenterLoginService;
import com.linkage.educloud.ucenter.login.shiro.UsernamePasswordUsertypeToken;

/**
* 校讯通的登录Realm
* @author caihz
*
*/
public class ShiroAndEduRealm extends AuthorizingRealm {
final static Logger log = LoggerFactory.getLogger(ShiroAndEduRealm.class);

@Autowired
private UcenterLoginService ucenterLoginService;

@Autowired
private Uc2XXTIfaceService xxtService;

/**
* 登录认证回调函数,登录时调用.
* @param authcToken 登录页面参数,用户名和密码等
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
UsernamePasswordUsertypeToken token = (UsernamePasswordUsertypeToken) authcToken;
String username = token.getUsername();
if (username == null){
throw new AccountException("账号不能为空");
}
//如果用户中心没有用户,则请求校讯通登录接口并查询用户中心对应的用户
String password = String.valueOf(token.getPassword());
//password = StringUtil.md5(password);
password = password.toLowerCase();
UcenterLoginUser user = ucenterLoginService.findUserByXxt(token.getUsername(), password, token.getUsertype());
if (user != null){
return new SimpleAuthenticationInfo(user, user.getLoginPass(), getName());
}else {
return null;
}

}

/**
* 登录认证通过后的权限查询函数, 由于目前用户中心前台页面不需要权限控制,所以没写,以后如果需要可扩展
*
* @see org.apache.shiro.authz.AuthorizationInfo
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

return info;
}
}


这下可终于解决了用户直接通过token鉴权登录的问题了。

例子:

@RequestMapping("/test")
public String test(HttpServletRequest request){
Subject subject = SecurityUtils.getSubject();
// subject.login(new UsernamePasswordToken(user.getPhone(), user.getLoginPass()));
//UsernamePasswordUsertypeToken up = new UsernamePasswordUsertypeToken("13816005001", "123456aA1", false, null, "3");
UsernamePasswordUsertypeToken up = new UsernamePasswordUsertypeToken("20212414", "4d45acd6c95faab86980ebbae7cad57c", false, request.getRemoteAddr(), "1");
//UsernamePasswordUsertypeToken up = new UsernamePasswordUsertypeToken("20212414", "bLaP7@3U", false, request.getRemoteAddr(), "1");
subject.login(up);
System.out.println("家长登录成功!");
return "redirect:/ucenter/index/index";
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: