若依免密登录

           最近做了一个微信扫码登录的功能整合到若依中,当扫码完成后,如何确定是哪个用户,以及权限有哪些,因为shiro的加密基于MD5所以密码不可逆,则不能从数据库查询后再解密,简单一些的话可以把需要登录的用户账号密码写死在配置文件中,我之前就是这么干的,但是这样做的话一旦修改密码,则需要修改配置文件,所以我想到了免密登录,在网上查了好多shiro的改造,也没整明白怎么回事,继承的类也是不知道干嘛的,所以自己研究了一下若依的实现过程,终于实现了可免密登录

第一步:如果需要免密登录就需要有个标志来确定是不是从微信扫码过来的,不然账号密码登录就不用输入密码也能进来,这显然是不对的

创建一个枚举,来当做标志

package com.clpc.un.framework.shiro.wxconfig;

public enum LoginType {
    PASSWORD("password"),
    NOPASSWORD("nopassword");

    private String code;

    LoginType(String code) {
        this.code = code;
    }

    public String getCode() {
        return code;
    }

}

第二步:我的业务是根据部门确定是哪个用户,写的比较low,还没做优化,在拿到部门id后就要进行登录,执行若依中原来的登录方法(改造过)

 public void execLogin(HttpServletRequest request,String deptId){
        log.info("登录用户部门Id:" + deptId);
        String loginName;//登录用户名
        if(deptId.equals("3") || deptId.equals("1190")){
            loginName = "admin";
        } else {
            loginName = "ChinaLife";
        }
        //执行免密登录
        loginController.ajaxLogin(request,loginName,"",true);
    }

第三步:上一步的登录方法我是进行了改造,根据request获取访问过来的路径,由此判断是微信,还是账号密码,这里面的token也是改造过的,生成token时把登录类型带上,就是我们写的token

   @PostMapping("/login")
    @ResponseBody
    public AjaxResult ajaxLogin(HttpServletRequest request,String username, String password, Boolean rememberMe)
    {
        //UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe);
        //根据地址判断是否是微信登录
        WxLoginToken token = null;
        if(request.getServletPath().equals("/weChat/wechatLogin")){
            token = new WxLoginToken(username, password, rememberMe, LoginType.NOPASSWORD);
        } else {
            token = new WxLoginToken(username, password, rememberMe, LoginType.PASSWORD);
        }

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

第四部:修改UsernameAndPasswordToken,继承后修改即可,大部分都是继承过来的,只有一个登录方法,和变量type是自己写的,目的是在token中携带登录类型

package com.clpc.un.framework.shiro.wxconfig;

import org.apache.shiro.authc.UsernamePasswordToken;

public class WxLoginToken extends UsernamePasswordToken {

    private LoginType type;

    public WxLoginToken() {
        super();
    }

    public WxLoginToken(String username, char[] password) {
        super(username, password);
    }

    public WxLoginToken(String username, String password) {
        super(username, password);
    }

    public WxLoginToken(String username, char[] password, String host) {
        super(username, password, host);
    }

    public WxLoginToken(String username, String password, String host) {
        super(username, password, host);
    }

    public WxLoginToken(String username, char[] password, boolean rememberMe) {
        super(username, password, rememberMe);
    }

    public WxLoginToken(String username, String password, boolean rememberMe,LoginType type) {
        super(username, password, rememberMe);
        this.type = type;
    }

    public WxLoginToken(String username, char[] password, boolean rememberMe, String host) {
        super(username, password, rememberMe, host);
    }

    public WxLoginToken(String username, String password, boolean rememberMe, String host) {
        super(username, password, rememberMe);
    }

    @Override
    public String getUsername() {
        return super.getUsername();
    }

    @Override
    public void setUsername(String username) {
        super.setUsername(username);
    }

    @Override
    public char[] getPassword() {
        return super.getPassword();
    }

    @Override
    public void setPassword(char[] password) {
        super.setPassword(password);
    }

    @Override
    public Object getPrincipal() {
        return super.getPrincipal();
    }

    @Override
    public Object getCredentials() {
        return super.getCredentials();
    }

    @Override
    public String getHost() {
        return super.getHost();
    }

    @Override
    public void setHost(String host) {
        super.setHost(host);
    }

    @Override
    public boolean isRememberMe() {
        return super.isRememberMe();
    }

    @Override
    public void setRememberMe(boolean rememberMe) {
        super.setRememberMe(rememberMe);
    }

    @Override
    public void clear() {
        super.clear();
    }

    @Override
    public String toString() {
        return super.toString();
    }

    public LoginType getType() {
        return type;
    }

    public void setType(LoginType type) {
        this.type = type;
    }
}

第五步:修改Realm,生成的token会传递给userRealm,所以这里面肯定是要修改的,把原来的token换成我们自己的token,并修改LoginService.login()方法

 /**
     * 登录认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException
    {
       //UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        //拿到token,此时token中存在登录类型,即是微信登录还是账号密码登录
        WxLoginToken upToken = (WxLoginToken) token;

        String username = upToken.getUsername();
        String password = "";
        if (upToken.getPassword() != null)
        {
            password = new String(upToken.getPassword());
        }

        User user = null;
        try
        {
            user = wxLoginService.login(username, password,upToken.getType());
        }
        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;
    }

第六步:修改LoginService,直接继承过来修改,尽量不改源文件,如果是通过账号密码登录则正常走原来的流程,验证密码之类的,如果来源于微信登录则直接去查数据库,不验证密码,直接返回查到的user

package com.clpc.un.framework.shiro.wxconfig;

import com.clpc.un.common.constant.Constants;
import com.clpc.un.common.exception.user.UserNotExistsException;
import com.clpc.un.common.utils.MessageUtils;
import com.clpc.un.framework.manager.AsyncManager;
import com.clpc.un.framework.manager.factory.AsyncFactory;
import com.clpc.un.framework.shiro.service.LoginService;
import com.clpc.un.project.system.user.domain.User;
import com.clpc.un.project.system.user.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class WxLoginService extends LoginService {

    @Autowired
    private IUserService userService;

    @Override
    public User login(String username, String password,LoginType type) {
        if ( type == LoginType.PASSWORD ){
            return super.login( username, password, type );
        } else {
            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();
            }
            recordLoginInfo(user);
            return user;
        }

    }

    @Override
    public void recordLoginInfo(User user) {
        super.recordLoginInfo(user);
    }


}

到此为止,免密登录就完成了,且不影响原有的密码登录,即使修改了密码也不影响我们微信登录,

此文作为自己的笔记,也给大家做个参考

文章手打不易,希望大家喜欢,多多支持,

  • 6
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值