1. 程式人生 > 其它 >基於ruoiy中shiro框架如何實現免密登入

基於ruoiy中shiro框架如何實現免密登入

技術標籤:日常總結shirojavaspring boot

基於ruoiy中shiro框架如何實現免密登入

所做專案與第三方合作,系統間存在一些介面呼叫,需要做授權登入。我們的專案整體使用springboot框架結合部分ruoyi的後臺管理框架,認證登陸採用了shiro框架,密碼在資料庫中經過鹽值(salt)+Md5加密,外部無法獲知密碼明文,導致無法驗證通過,所以想到了免密登入的方式解決。

若依框架官網:https://gitee.com/y_project/RuoYi

經過一番摸索,也總算弄出來了,在此記錄一下

1,新增一個登入型別列舉類LoginType

package com.ht.framework.
shiro.token; /** * 登入型別列舉類 * * @author hcg */ public enum LoginType { /** * 密碼登入 */ PASSWORD("password"), /** * 免密碼登入 */ NOPASSWD("nopasswd"); private String desc; LoginType(String desc) { this.desc = desc; } public
String getDesc() { return desc; } }

2、自定義登入Token,繼承UsernamePasswordToken類,通過構造方法區分密碼登入和免密登入。

package com.ht.framework.shiro.token;

import org.apache.shiro.authc.UsernamePasswordToken;

/**
 * 自定義登入Token
 *
 * @author huang
 */
public class UserToken extends UsernamePasswordToken
{
    private
static final long serialVersionUID = 1L; private LoginType type; public UserToken() { } //需要密碼 public UserToken(String username, String password, LoginType type, boolean rememberMe) { super(username, password, rememberMe); this.type = type; } //免密 public UserToken(String username, LoginType type) { super(username, "", false, null); this.type = type; } public UserToken(String username, String password, LoginType type) { super(username, password, false, null); this.type = type; } public LoginType getType() { return type; } public void setType(LoginType type) { this.type = type; } }

3、對應Realm中新增登入型別判斷,例如UserRealm

/**
 * 登入認證
 */
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException
{
	UserToken upToken = (UserToken) token;
	LoginType type = upToken.getType();
	String username = upToken.getUsername();
	String password = "";
	if (upToken.getPassword() != null)
	{
		password = new String(upToken.getPassword());
	}

	User user = null;
	try
	{
		if (LoginType.PASSWORD.equals(type))
		{
		   //需要密碼登入
		 	user = loginService.login(username, password);
		}
		else if (LoginType.NOPASSWD.equals(type))
		{
		  //免密登入
			user = loginService.login(username);
		}
	}
	catch (CaptchaException e)
	{
		throw new AuthenticationException(e.getMessage(), e);
	}
	catch (UserNotExistsException e)
	{
		throw new UnknownAccountException(e.getMessage(), e);
	}
	catch (UserPasswordNotMatchException e)
	{
		throw new IncorrectCredentialsException(e.getMessage(), e);
	}
	catch (UserPasswordRetryLimitExceedException e)
	{
		throw new ExcessiveAttemptsException(e.getMessage(), e);
	}
	catch (UserBlockedException e)
	{
		throw new LockedAccountException(e.getMessage(), e);
	}
	catch (RoleBlockedException e)
	{
		throw new LockedAccountException(e.getMessage(), e);
	}
	catch (Exception e)
	{
		log.info("對使用者[" + username + "]進行登入驗證..驗證未通過{}", e.getMessage());
		throw new AuthenticationException(e.getMessage(), e);
	}
	SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
	return info;
}

4,LoginService新增login方法,去掉密碼驗證。

 /**
     * 登入
     */
    public User login(String username)
    {
        // 驗證碼校驗
        if (!StringUtils.isEmpty(ServletUtils.getRequest().getAttribute(ShiroConstants.CURRENT_CAPTCHA)))
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
            throw new CaptchaException();
        }
        // 使用者名稱或密碼為空 錯誤
        if (StringUtils.isEmpty(username))
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
            throw new UserNotExistsException();
        }

        // 使用者名稱不在指定範圍內 錯誤
        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
            throw new UserPasswordNotMatchException();
        }

        // 查詢使用者資訊
        User user = userService.selectUserByLoginName(username);

        if (user == null)
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.not.exists")));
            throw new UserNotExistsException();
        }

        if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.delete")));
            throw new UserDeleteException();
        }

        if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.blocked", user.getRemark())));
            throw new UserBlockedException();
        }

        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        recordLoginInfo(user);
        return user;
    }

5、在對應的登入方法中傳入LoginType.NOPASSWD呼叫

需要密碼的登入方式

        UserToken token=new UserToken(username,password, LoginType.PASSWORD,rememberMe);
        Subject subject = SecurityUtils.getSubject();
        try
        {
            subject.login(token);
            return success();
        }
        catch (AuthenticationException e)
        {
            String msg = "使用者或密碼錯誤";
            if (StringUtils.isNotEmpty(e.getMessage()))
            {
                msg = e.getMessage();
            }
            return error(msg);
        } 

免密登入方式

        User user = userMapper.selectUserByLoginName(username);
        UserToken token=new UserToken(user.getLoginName(), LoginType.NOPASSWD);
        Subject subject = SecurityUtils.getSubject();
        subject.login(token);
        //重定向首頁地址
        return "redirect:/newindex";    

到此為止,輸入正確的地址就可以實現免密登入了!!

特別宣告

此記錄是在ruoyi的shiro框架上進行的進一步修改,只做筆記之用。

如無用你可以嘗試:

如何實現使用者免密登入配置方法

https://blog.csdn.net/xxfamly/article/details/92839999