ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Shiro的基本使用

2021-11-05 03:00:15  阅读:131  来源: 互联网

标签:基本 使用 Shiro org apache import public shiro user


Shiro

Apache Shiro是一个功能强大且易于使用的 Java 安全框架,可执行身份验证、授权、加密和会话管理。

image-20211012234753255

  • Authentication:身份认证/登录,验证用户是不是拥有相应的身份;
  • Authorization:授权,即权限验证,判断某个已经认证过的用户是否拥有某些权限访问某些资源,一般授权会有角色授权和权限授权;
  • SessionManager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的,web 环境中作用是和 HttpSession 是一样的;
  • Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;

它有三个核心的组件:Subject, SecurityManagerRealms.

  • Subject:即当前的操作用户;

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

  • Realms:Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。

官方的十分钟入门文档:https://shiro.apache.org/10-minute-tutorial.html

以下为入门文档中的例子文件:

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class Quickstart {

    private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);


    public static void main(String[] args) {

        DefaultSecurityManager securityManager = new DefaultSecurityManager();
        IniRealm iniRealm = new IniRealm("classpath:shiro.ini");
        securityManager.setRealm(iniRealm);


        SecurityUtils.setSecurityManager(securityManager);

        //在几乎所有环境中,您都可以通过以下调用获取当前正在执行的用户:
        Subject currentUser = SecurityUtils.getSubject();

        //在用户与应用程序的当前会话期间向其提供内容,您可以获取他们的会话:(它不需要 HTTP 环境!)
        Session session = currentUser.getSession();
        session.setAttribute("someKey", "aValue");
        String value = (String) session.getAttribute("someKey");
        if (value.equals("aValue")) {
            log.info("Retrieved the correct value! [" + value + "]");
        }

        //对已知用户进行这些检查。我们Subject上面的实例代表当前用户,判断是否已经登录了
        if (!currentUser.isAuthenticated()) {
            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
            token.setRememberMe(true);
            //如果登录尝试失败了怎么办,则会捕捉各种异常,并及时做出处理
            try {
                currentUser.login(token);
            } catch (UnknownAccountException uae) {
                log.info("There is no user with username of " + token.getPrincipal());
            } catch (IncorrectCredentialsException ice) {
                log.info("Password for account " + token.getPrincipal() + " was incorrect!");
            } catch (LockedAccountException lae) {
                log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                        "Please contact your administrator to unlock it.");
            }

            catch (AuthenticationException ae) {

            }
        }

        //输出已登录的用户信息:(测试角色)
        log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");

        //测试其是否具有特定的作用:
        if (currentUser.hasRole("schwartz")) {
            log.info("May the Schwartz be with you!");
        } else {
            log.info("Hello, mere mortal.");
        }

        //查看他们是否有权对某种类型的实体采取行动:(测试输入权限)
        if (currentUser.isPermitted("lightsaber:wield")) {
            log.info("You may use a lightsaber ring.  Use it wisely.");
        } else {
            log.info("Sorry, lightsaber rings are for schwartz masters only.");
        }

        //查看用户是否有能力访问某个类型的特定实例:
        if (currentUser.isPermitted("winnebago:drive:eagle5")) {
            log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
                    "Here are the keys - have fun!");
        } else {
            log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
        }

        //用户注销:
        currentUser.logout();

        System.exit(0);
    }
}

小总结:

---认证:

1、subject获取用户; SecurityUtils.getSubject();

2、UsernamePasswordToken 封装数据

3、登录; subject.login(token);

之后就进行一些登录中的某些异常判断。

----拦截:分为三步

1、创建realm对象;

2、efaultWebSecurityManager

3、ShiroFilterFactoryBean;所有授权拦截操作都这里配置

导入shiro依赖

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.7.1</version>
</dependency>

配置shiro

需要现有一个UserRealm:

package com.vxzx.config;

import com.vxzx.pojo.User;
import com.vxzx.server.UserServer;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

public class UserRealm extends AuthorizingRealm {
    @Autowired
    UserServer userServer;

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了授权的方法:====》AuthorizationInfo");
        //将给用户进行授权,让用户具有一定的权限:   SimpleAuthorizationInfo
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //让所有用户都拥有user:add的权限:
//        info.addStringPermission("user:add");

        //拿到当前用户,让其自动识别数据库里面的拥有的权限:
        Subject subject = SecurityUtils.getSubject();
        //获取User:
        User principal = (User) subject.getPrincipal();
        //设置权限:
        info.addStringPermission(principal.getPerms());
        return info;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行了认证的方法:====》AuthenticationInfo");

        UsernamePasswordToken userToken = (UsernamePasswordToken)authenticationToken;
        //从数据库中获取用户信息:
        User user = userServer.query(userToken.getUsername());

        if (user==null){
            return null;
        }
        //密码认证:
        return new SimpleAuthenticationInfo(user,user.getPwd(),"");
    }
}

ShiroConfig:里面配置一些拦截的配置

package com.vxzx.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
    //ShiroFilterFactoryBean:第三步(基于第二步)
    @Bean
    public ShiroFilterFactoryBean factoryBean(@Qualifier("securityManager")DefaultSecurityManager defaultSecurityManager){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //关联第二步中的securityManager:
            //设置安全管理器:
        bean.setSecurityManager(defaultSecurityManager);

        //添加shiro的内置过滤器:
        /*
        *   anno : 无需认证就可以访问
        *   authc :必须认证才可以访问
        *   user : 必须拥有 记住我 才可以访问
        *   perms : 拥有对某个资源的权限
        *   roles : 拥有对某个角色的访问权
        * */
        Map<String, String> filters = new LinkedHashMap();
        filters.put("/add","authc");
        filters.put("/update","authc");
        //授权:未授权的情况下,或跳转到未授权的页面去;
        filters.put("/add","perms[user:add]");
        filters.put("/update","perms[user:update]");

        //过滤请求:
        bean.setFilterChainDefinitionMap(filters);

        //权限不够,跳转到专门页面去:
        bean.setUnauthorizedUrl("/unauthorized");

        //设置登录请求:
        bean.setLoginUrl("/tologin");

        //

        return bean;
    }

    //DefaultWebSecurityManager: 第二步(基于第一步)
    @Bean(name="securityManager")
    public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("user")UserRealm userRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联第一步中的userRealm:
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    //创建realm对象:第一步
    @Bean(name="user")
    public UserRealm userRealm(){
        return  new UserRealm();
    }

    //整合ShiroDialect, 可以整合Shiro Thymeleaf
    @Bean
    public ShiroDialect shiroThy(){
        ShiroDialect dialect = new ShiroDialect();
        return dialect;
    }
}

controller配置前端页面的跳转:

package com.vxzx.controller;

import com.vxzx.dao.UserMapper;
import com.vxzx.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class RouterC {
    @Autowired
    UserMapper userMapper;

    @RequestMapping({"/","index"})
    public String toIndex(Model model){
        model.addAttribute("msg","Hello,Shiro");
        return "index";
    }

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

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

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

    @RequestMapping("/login")
    public String login(String username,String password,Model model){
        //获取当前正在执行的用户
        Subject subject = SecurityUtils.getSubject();
        //封装用户数据:
        UsernamePasswordToken token = new UsernamePasswordToken(username,password);

            try {
                subject.login(token);
                return "index";
            } catch (UnknownAccountException e) {
                model.addAttribute("msg","用户名不正确");
                return "/user/login";
            }catch (IncorrectCredentialsException e){
                model.addAttribute("msg","密码不正确");
                return "/user/login";
            }
    }

    @RequestMapping("/unauthorized")
    @ResponseBody
    public String unauthorized(){
        return "权限不够,无法访问!";
    }

    @RequestMapping("/logout")
    public String logout(){
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "user/login";
    }
}

其中还涉及到mybatis的配置及前端页面的配置,这些都自行配置就行,主要说明shiro的作用及配置。

标签:基本,使用,Shiro,org,apache,import,public,shiro,user
来源: https://www.cnblogs.com/vxzx/p/15511428.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有