Shiro安全框架的基本使用与相关开发笔记

Shiro是一个功能强大、灵活的开源安全框架,可以干净地处理身份验证、授权、会话管理和加密。本文将记录Shiro相关的开发笔记。

Shiro官网给出的架构图:

从下图中可以看出Shiro主要有Subject(用户),ShiroSecurityManager(操作管理用户) 和Realm(操作安全数据进行授权,认证)组成

Shiro官网:Apache Shiro | Simple. Java. Security.

首先引入相关依赖

  <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.8.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>1.8.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.8.0</version>
            <scope>compile</scope>
        </dependency>

自定义Realm

根据上面的框架,我们首先要编写一个自定义的realm用于处理数据如用户名,密码,访问权限等

public class UserRealm extends AuthorizingRealm {

    @Autowired
    UserService userService;

    
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        //new一个AuthorizationInfo()用于管理角色和权限
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        
        //从Principal()中获取我们在下面 SimpleAuthenticationInfo 存入的user对象
        User currentUser = (User) SecurityUtils.getSubject().getPrincipal();

        //从user对象中读取我们perm值,perm在数据库中定义了,为权限信息
        //Perm如user:vip
        info.addStringPermission(currentUser.getPerm());
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        //读取传入的Token
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        
        //通过token中的信息取到user对象
        User user = userService.getUserByName(token.getUsername());
        //如果用户不存在
        if(user==null){
            //返回null, shiro抛出UnknownAccountException异常
            return null;
        }

        //返回AuthenticationInfo
        //包含三个参数Object principal, Object credentials, String realmName
        //principal传入我们需要储存的对象,credentials即密码
        return new SimpleAuthenticationInfo(user,user.getPassword(),"");
    }
}

其中 SimpleAuthorizationInfo 用于管理角色,权限等信息

SimpleAuthenticationInfo用于管理认证信息

 编写shiro配置文件

@Configuration
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(defaultWebSecurityManager);
        //创建一个map存储授权信息
        Map<String, String> filterChainDefinitionMap=new LinkedHashMap<>();

        //设置vip界面的访问权限为user:vip
        filterChainDefinitionMap.put("/pages/vip","perms[user:vip]");

        //设置Pages下的所有界面需认证才能访问
        filterChainDefinitionMap.put("/pages/*","authc");

        bean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        //设置登陆界面
        bean.setLoginUrl("/toLogin");

        //设置未授权错误界面
        bean.setUnauthorizedUrl("noauth");
        return bean;
    }

    @Bean(name="securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        //创建securityManager 对象,传入Realm
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    @Bean
    public UserRealm userRealm(){
        return new UserRealm();
    };
}

编写登录控制器

 @GetMapping("/login")
    public String login(String username, String password, Model model){

        //将前端传入的用户名和密码存入UsernamePasswordToken中
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        //获取当前用户的subject 对象
        Subject subject = SecurityUtils.getSubject();
        try {
            //登录
            subject.login(token);
            return "redirect:/index";

        //UnknownAccountException 用户名错误
        }catch (UnknownAccountException e){
            model.addAttribute("error","Wrong username");
            return "login";

        //IncorrectCredentialsException 密码错误
        }catch (IncorrectCredentialsException e){
            model.addAttribute("error","wrong password");
            return "login";
        }
    }

猜你喜欢

转载自blog.csdn.net/yscjhghngh/article/details/122674989