zoukankan      html  css  js  c++  java
  • (三)shiro的认证


    认证思路

    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

  • 相关阅读:
    java基础--13.Regex正则表达式
    java基础面试题12--Integer--自动拆装箱
    java基础面试题11--String--最大公共子串
    笔记本wif模块接线备忘
    windows环境下gcc/g++ 编译器 乱码问题解决
    转轮加密机 加解密 (C语言实现)
    windbg
    windows 内核调试
    python源码编译(嵌入式)
    Android studio
  • 原文地址:https://www.cnblogs.com/young-youth/p/11665596.html
Copyright © 2011-2022 走看看