(三)shiro的认证

版权声明:转载请给出原文链接 https://blog.csdn.net/youngyouth/article/details/86618524


认证思路

  1. 调用 SecurityUtils.getSubject() 方法,获取当前的 Subject 对象 ;

  2. 调用 Subject.isAuthenticated() 测试当前的用户,即 Subject 是否以及被认证,即是否登录 ;

  3. 如果没有被认证,则进行认证操作;

  4. 将用户名和密码封装成 UsernamePasswordToken 对象;

  5. 自定义 Realm 的方法,从数据库获取对应的记录,返回给 shiro

    如果是仅仅完成登录,则继承 AuthenticatingRealm 类,实现 doGetAuthenticationInfo(AuthenticationToken) 方法 ;

  6. 调用 Subject.login(AuthenticationToken) 方法,执行登录 ;

  7. shiro 完成密码的比对 。


自定义用于登录检验的Realm的思路

在认证的时候, Subject.login(AuthenticationToken) 方法,传进去的参数,最终被传到了 AuthenticatingRealm 的自定义子类中,用于认证的方法中;

  1. 将方法中token参数,强转为 UsernamePasswordToken 对象;

  2. UsernamePasswordToken 中获取 用户名 ;

  3. 调用数据库方法,获取此用户名对用的记录;

  4. 如若此用户不存在,则抛出 UnknownAccountException 异常;

  5. 用户存在的情况下,根据实际情况看是否需要抛出其他 AuthenticationException 异常,比如:用户被锁定异常

  6. 根据用户情况,构建 AuthenticationInfo 对象返回,最常用的是实现类是:SimpleAuthenticationInfo

    如果不需要进行盐值加密,则调用有三个参数的构造器;

    1. principal : 认证的实体信息,也就上面我们是使用什么信息进行认证,比如这里就是使用 用户名 ;
    2. credentials:数据库中保存的密码;
    3. realmName:当前 realm 的名字,调用父类的 getName() 方法即可 ;

代码实现

控制器代码:

 @RequestMapping(value = "/isAllowLogin", method = {RequestMethod.POST})
    @ResponseBody
    public String isAllowLogin(@RequestParam("username") String username, @RequestParam("password") String password) throws IOException {
        JSONObject jsonObject = new JSONObject();
        Subject subject = SecurityUtils.getSubject();
        if (!subject.isAuthenticated()) {
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);
            try {
                subject.login(token);
            } catch (AuthenticationException e) {
                jsonObject.put("result", "0");
                return jsonObject.toJSONString();
            }
        }

        jsonObject.put("result", "1");
        return jsonObject.toJSONString();
    }

自定义Realm代码:

@Service
public class ShiroRealm extends AuthenticatingRealm {

    @Autowired
    private UserMapper userMapper;

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
       UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String username = token.getUsername();

        User user = userMapper.findUserByName(username);
        if (null == user) {
            throw new UnknownAccountException("用户名或密码错误");
        }
        String password = user.getUserPass();
        AuthenticationInfo info = new SimpleAuthenticationInfo(username, password, getName());

		 return info;
    }
}

后记

shiro 的校验通过以后,同一个 session 对应的浏览器再次输入 任意登录信息 都会校验通过,这是 shiro 拿缓存了,没有走 realm 校验 ;

要想登出,可以使用在受保护页面那里配置一个 logout 进行登出操作;

   <property name="filterChainDefinitions">
            <value>
                /logout.action = logout
               ...
               ....
               ...
            </value>
        </property>

这里注意,前面的路径随便写,无论其存在不存在,只要后面写成 logout 就行, shiro 就会执行登出操作;其原理应该是销毁了对应的 session

猜你喜欢

转载自blog.csdn.net/youngyouth/article/details/86618524
今日推荐