基於ruoiy中shiro框架如何實現免密登入
阿新 • • 發佈:2020-12-10
基於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框架上進行的進一步修改,只做筆記之用。
如無用你可以嘗試: