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

1 篇文章 0 订阅

1.今天遇到了一个棘手的问题,在此写下博客记录下来,用于提醒自己,以及帮助以后会遇到这样的问题的人

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

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

            

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

 

 

 

 

 

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

 

 



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代码如下:

 



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";
	}

 

 

 

 

 

 

  • 33
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
以下是使用Spring加Shiro写一个简单的登录功能的详细代码。 1. 配置Shiro 在Spring的配置文件,配置Shiro的相关内容: ``` <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="myRealm"/> </bean> <bean id="myRealm" class="com.example.MyRealm"/> <bean class="org.springframework.web.filter.DelegatingFilterProxy"> <property name="targetFilterLifecycle" value="true"/> </bean> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"/> <property name="loginUrl" value="/login"/> <property name="successUrl" value="/index"/> <property name="filterChainDefinitions"> <value> /login = anon /logout = logout /** = authc </value> </property> </bean> ``` 在上述配置,我们配置了Shiro的安全管理器、自定义Realm、Shiro的过滤器等。 2. 编写登录页面 在登录页面,我们需要使用表单来提交用户名和密码。为了与Shiro进行集成,我们需要在表单添加名为“rememberMe”的复选框,用于实现记住我功能。 ``` <form method="post" action="/login"> <input type="text" name="username" placeholder="用户名"> <input type="password" name="password" placeholder="密码"> <input type="checkbox" name="rememberMe">记住我 <button type="submit">登录</button> </form> ``` 3. 编写自定义Realm 我们需要继承Shiro的Realm类,并实现其的认证和授权方法。 ``` public class MyRealm extends AuthorizingRealm { /** * 认证方法 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken upToken = (UsernamePasswordToken) token; String username = upToken.getUsername(); String password = new String(upToken.getPassword()); // 根据用户名从数据库获取用户信息 User user = userService.findByUsername(username); if (user == null) { throw new UnknownAccountException("用户不存在"); } if (!password.equals(user.getPassword())) { throw new IncorrectCredentialsException("密码错误"); } return new SimpleAuthenticationInfo(user, password, getName()); } /** * 授权方法 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { User user = (User) principals.getPrimaryPrincipal(); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.setRoles(user.getRoles()); info.setStringPermissions(user.getPermissions()); return info; } } ``` 在上述代码,我们从数据库获取用户信息,并对用户名和密码进行验证。如果验证通过,则返回一个AuthenticationInfo对象,在后续的认证流程使用。 在授权方法,我们从用户信息获取用户的角色和权限等信息,用于后续的授权流程。 4. 编写登录Controller 在登录Controller,我们需要处理用户提交的表单数据,并进行Shiro认证流程。 ``` @Controller public class LoginController { @RequestMapping("/login") public String login(HttpServletRequest request) { String exceptionClassName = (String) request.getAttribute("shiroLoginFailure"); if (exceptionClassName != null) { if (UnknownAccountException.class.getName().equals(exceptionClassName)) { request.setAttribute("errorMsg", "用户不存在"); } else if (IncorrectCredentialsException.class.getName().equals(exceptionClassName)) { request.setAttribute("errorMsg", "密码错误"); } else if (AuthenticationException.class.getName().equals(exceptionClassName)) { request.setAttribute("errorMsg", "认证失败"); } else if (LockedAccountException.class.getName().equals(exceptionClassName)) { request.setAttribute("errorMsg", "账号被锁定"); } else { request.setAttribute("errorMsg", "未知错误"); } } return "login"; } } ``` 在上述代码,我们判断Shiro认证过程是否出现异常,并将异常信息存储到request,用于在登录页面显示错误信息。 5. 编写登录成功跳转Controller 在登录成功后,我们需要跳转到指定的页面。在Spring MVC,我们可以使用redirect方式来实现。 ``` @Controller public class IndexController { @RequestMapping("/index") public String index() { return "index"; } } ``` 在上述代码,我们配置了一个/index的请求映射,用于跳转到index页面。 6. 编写注销Controller 在注销Controller,我们需要清除Shiro的缓存信息,并跳转到登录页面。 ``` @Controller public class LogoutController { @RequestMapping("/logout") public String logout() { SecurityUtils.getSubject().logout(); return "redirect:/login"; } } ``` 在上述代码,我们使用SecurityUtils.getSubject()来获取当前用户的Subject对象,并调用其logout()方法来清除缓存。最后,我们使用redirect方式跳转到登录页面。 以上就是使用Spring加Shiro写一个简单的登录功能的详细代码
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值