Shrio

Shrio

Shiro和Spring Security比较

(1)Shiro比Spring更容易使用,实现和最重要的理解
(2)Spring Security更加知名的唯一原因是因为品牌名称
(3)“Spring”以简单而闻名,但讽刺的是很多人发现安装Spring Security很难
(4)Spring Security却有更好的社区支持
(5)Apache Shiro在Spring Security处理密码学方面有一个额外的模块
(6)Spring-security 对spring 结合较好,如果项目用的springmvc ,使用起来很方便。但是如果项目中没有用到spring,那就不要考虑它了。
(7)Shiro 功能强大、且 简单、灵活。是Apache 下的项目比较可靠,且不跟任何的框架或者容器绑定,可以独立运行


Shiro基础介绍

1. Shiro三个核心组件

1.1 Subject
  Subject:即“当前操作用发户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。但考虑到大多数目的和用途,你可以把它认为是Shiro的“用户”概念。Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。

1.2 SecurityManager
  SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。

1.3 Realm
  Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。
  从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。
  Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似INI的文本配置资源以及属性文件等。如果缺省的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm实现。

2. Shiro相关类介绍

(1)Authentication 认证 ---- 用户登录
(2)Authorization 授权 — 用户具有哪些权限
(3)Cryptography 安全数据加密
(4)Session Management 会话管理
(5)Web Integration web系统集成
(6)Interations 集成其它应用,spring、缓存框架

3. Shiro 特点

(1)易于理解的 Java Security API;
(2)简单的身份认证(登录),支持多种数据源(LDAP,JDBC,Kerberos,ActiveDirectory 等);
(3)对角色的简单的签权(访问控制),支持细粒度的签权;
(4)支持一级缓存,以提升应用程序的性能;
(5)内置的基于 POJO 企业会话管理,适用于 Web 以及非 Web 的环境;
(6)异构客户端会话访问;
(7)非常简单的加密 API;
(8)不跟任何的框架或者容器捆绑,可以独立运行

Spring Boot整合Shiro代码实战

1. 导入依赖

 <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.7.0</version>
        </dependency>

2. 配置文件

ShiroConfig

@Configuration
public class ShiroConfig {
     

    //ShiroFilteFactoryBean
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultSecurityManager") DefaultWebSecurityManager defaultSecurityManager){
     
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //设置安全管理器
        bean.setSecurityManager(defaultSecurityManager);
        //添加shiro的内置过滤器
        /**
         * anno :无需认证就可以访问
         * authc:必须认证才能访问
         * user: 必须拥有 记住我 功能才能用
         * perms: 拥有对某个资源的权限才能访问
         * role: 拥有某个角色权限才能访问
         */
        LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();
        //授权
        linkedHashMap.put("/add","perms[user:add]");
        //认证
        //linkedHashMap.put("/add","authc");
        linkedHashMap.put("/update","authc");
        bean.setFilterChainDefinitionMap(linkedHashMap);
        //未认证默认跳转登录页
        bean.setLoginUrl("/");
        //未授权跳转
        bean.setUnauthorizedUrl("/noAuth");
        return bean;
    }

    //DefaultWebSecurityManage
    @Bean
    public DefaultWebSecurityManager defaultSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
     
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    //创建realm对象 创建类
    @Bean
    public UserRealm userRealm(){
     
        return new UserRealm();
    }

}

UserRealm

//自定义的realm
public class UserRealm extends AuthorizingRealm {
     
    @Autowired
    private UserService userService;

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
     
        System.out.println("执行了---->授权");
        //进行授权
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //拿到当前登录对象  添加对象的权限列
        Subject subject = SecurityUtils.getSubject();
        User principal = (User) subject.getPrincipal();
        info.addStringPermission("user:add");
        return info;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken Token) throws AuthenticationException {
     
        System.out.println("执行了---->认证");
        //用户名 密码
        UsernamePasswordToken userToken = (UsernamePasswordToken) Token;
        User user = userService.UserList(userToken.getUsername());
        if (user == null){
     
            return null;
        }
        //MD5盐值加密
        //Md5Hash md5Hash = new Md5Hash(user.getPwd(), user.getName(), 3);
        return new SimpleAuthenticationInfo(user,user.getPwd(), ByteSource.Util.bytes(user.getName()),"");
    }
}

3. Controller

@Controller
public class UserController {
     

    @RequestMapping({
     "/","/index"})
    public String index(){
     
        return "login";
    }

    @RequestMapping("/add")
    public String add(){
     
        return "user/add";
    }

    @RequestMapping("/update")
    public String update(){
     
        return "user/update";
    }
    
    @RequestMapping("/toLogin")
    public String toLogin(String account,String password,Model model){
     
        //获取当前用户
        Subject subject = SecurityUtils.getSubject();
        //封装用户数据
        UsernamePasswordToken token = new UsernamePasswordToken(account, password);
        try {
     
            subject.login(token);//执行登录的方法
            return "index";
        } catch (UnknownAccountException uae) {
      //用户名不存在
            model.addAttribute("msg","用户名错误");
            return "login";
        } catch (IncorrectCredentialsException ice) {
      //密码不存在
            model.addAttribute("msg","密码错误");
            return "login";
        } catch (LockedAccountException lae) {
     
            model.addAttribute("msg","账号异常");
            return "login";
        } catch (AuthenticationException ae) {
     
            model.addAttribute("msg","账号异常");
            return "login";
        }
    }
    
    @RequestMapping("/noAuth")
    @ResponseBody
    public String noAuth(){
     
        return "未授权,禁止访问!";
    }
}

你可能感兴趣的:(JavaEE)