El externo no puede detectar la excepción lanzada por el método doGetAuthenticationInfo de Realm

En el marco de permisos de shiro, el subject.login (token) del método de inicio de sesión del usuario ingresará al método de autenticación doGetAuthenticationInfo de la clase personalizada UserNamePasswordRealm. Generalmente, doGetAuthenticationInfo se escribe de la siguiente manera:

    /**
     * 登录认证  subject.login()登录时调用
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //加这一步的目的是在Post请求的时候会先进认证,然后在到请求
        UserToken user = (UserToken)authenticationToken;
        if (authenticationToken.getPrincipal() == null) {
            return null;
        }
        if (user == null) {
            //这里返回后会报出对应异常
            return null;
        } else {
            SysUser sysUser = null;
            if (LoginTypeEnum.MANAGER.getType().equals(user.getCallType())) {
                sysUser = userService.findByName(user.getUserName());
                if(sysUser == null){
                    return null;
                }
                user.setSalt(sysUser.getSalt());
                try {
                    Map<String, Object> map = getSysUserInfo(sysUser, 1);
                    String sysEmp = JSONObject.toJSONString(map);
                    user.setToken(map.get("token").toString());
                    user.setId(sysUser.getId());
                    user.setCompanyId(sysUser.getCompanyId());
                    user.setCompanyName(sysUser.getCompanyName());
                    redisUtil.set("ecommerece_sys" + "_" + sysUser.getId().toString(), sysEmp, 36000);
                    redisUtil.set("ecommerece_sys" + "_" + sysUser.getId().toString() + "_info", JSONObject.toJSONString(sysUser), 36000);
                }  catch (Exception e) {
                    e.printStackTrace();
                }
            }
            //这里验证authenticationToken和simpleAuthenticationInfo的信息
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                    user, //用户
                    sysUser.getPassword(), //密码
                    ByteSource.Util.bytes(sysUser.getSalt()),//salt=username+salt
                    getName()  //realm name
            );
            return authenticationInfo;
        }
    }

Se harán varios juicios lógicos en este método, pero quiero personalizar una excepción en este método doGetAuthenticationInfo (), de la siguiente manera:

if(!sysOrganization.getLoginScope().contains("1")){
                    throw new BusinessRuntimeException(Global.FORBIDDEN_ERROR, "您没有权限登录后台管理端,请联系管理员");
                }

Se encuentra que no se puede capturar con precisión ninguna excepción externa. Las excepciones detectadas por el inicio de sesión externo se reescriben uniformemente como excepciones AuthenticationException (la clase principal de la excepción IncorrectaCredentialsException y otras excepciones), y el contenido del mensaje de la excepción también se reescribe.

En conclusión

El externo no puede detectar la excepción lanzada por el método doGetAuthenticationInfo porque el código fuente no es un problema con su propio código.
Si no tiene la capacidad de reescribir el código fuente, ¿qué debe hacer si desea detectar varias excepciones y mostrar varias indicaciones en la interfaz?

Mi solución temporal es que doGetAuthenticationInfo solo se usa para verificar el nombre de usuario y la contraseña, y la excepción de autenticación se captura directamente desde el exterior.

Otras verificaciones diversas se mueven del método doGetAuthenticationInfo para iniciar sesión, como la excepción BusinessRuntimeException personalizada, no la coloque en doGetAuthenticationInfo () para juzgar, pero juzgue antes de ir a subject.login (userToken); y dé una excepción, muy bien .

El código de inicio de sesión modificado es el siguiente:

 @PostMapping("/login/anon")
    @ApiResponses({ @ApiResponse(code = Global.SUCCESS, message = "成功!"),
            @ApiResponse(code = Global.PARAM_ERROR, message = "参数错误!"),
            @ApiResponse(code = Global.INTERNAL_SERVER_ERROR, message = "出错了!") })
    @ApiOperation(value = "管理后台登录", httpMethod = "POST", notes = " 管理后台登录")
    public SwaggerResultUtil<Object> login(HttpServletRequest request,@RequestBody User user) {
        SwaggerResultUtil<Object> result = new SwaggerResultUtil<>();
        //添加用户认证信息
        Subject subject = SecurityUtils.getSubject();
        UserToken userToken = new UserToken(
                user.getUserName(),
                user.getPassword(),
                LoginTypeEnum.MANAGER.getType()
        );
        try {
            SysUser sysUser = userService.findByName(user.getUserName());
            if(sysUser.getAccountType()==3){
                SysEmployee sysEmployee = sysEmployeeMapper.selectByAccount(user.getUserName());
                SysOrganization sysOrganization = sysOrganizationMapper.selectByPrimaryKey(sysEmployee.getOrganizationId());
                if(!sysOrganization.getLoginScope().contains("1")){
                    throw new BusinessRuntimeException(Global.FORBIDDEN_ERROR, "您没有权限登录后台管理端,请联系管理员");
                }
            }
            //进行验证,这里可以捕获异常,然后返回对应信息
            subject.login(userToken);
            UserToken token= (UserToken) subject.getPrincipal();
            token.setSalt(null);
            token.setPassword(null);
            result.setData(token);
            result.setCode(Global.SUCCESS);
            result.setMsg("登录成功");
            //添加日志
            SysLog sysLog=new SysLog();//自己写的日志类
            String  requestIp  =request.getRemoteAddr();
            sysLog.setOperatorIp(requestIp);
            sysLog.setType(Byte.valueOf(LoginTypeEnum.MANAGER.getType()));
            SysUser byName = sysUserMapper.findByName(user.getUserName());
            sysLog.setOperatorName(byName.getName());
            sysLog.setOperatorAccount(user.getUserName());
            sysLog.setAction("管理后台登录");
            sysLog.setCreateDate(System.currentTimeMillis());
            sysLogMapper.insert(sysLog);
        } catch (BusinessRuntimeException e){
            e.printStackTrace();
            result.setCode(Global.INTERNAL_SERVER_ERROR);
            result.setMsg(e.getMsg());
            return result;
        } catch (AuthenticationException e) {
            e.printStackTrace();
            result.setCode(Global.INTERNAL_SERVER_ERROR);
            result.setMsg("账号或密码错误!");
            return result;
        } catch (AuthorizationException e) {
            e.printStackTrace();
            result.setCode(Global.INTERNAL_SERVER_ERROR);
            result.setMsg("没有权限!");
            return result;
        }
        return result;
    }

Referencia: https://www.cnblogs.com/wangxin37/p/6397969.html 

Supongo que te gusta

Origin blog.csdn.net/zhangleiyes123/article/details/109111278
Recomendado
Clasificación