zoukankan      html  css  js  c++  java
  • Apache Shiro

    目录:

        1、What is Apache Shiro?
        2、shiro demo: 身份认证使用textRealm
        3、身份认证使用jdbcRealm
        4、编程式授权
        5、shiro + spring

    1、What is Apache Shiro?  <--返回目录

      10 Minute Tutorial on Apache Shiro:http://shiro.apache.org/10-minute-tutorial.html

      Apache Shiro is a powerful and easy to use Java security framework that offers developers an intuitive yet comprehensive solution to authentication, authorization, cryptography, and session management.

      Shiro:java安全框架,提供认证、授权、加密和回话管理。

      获取当前用户:

    Subject currentUser = SecurityUtils.getSubject();

      获取用户session:

    Session session = currentUser.getSession();
    session.setAttribute( "someKey", "aValue" );

      用户认证:

    if ( !currentUser.isAuthenticated() ) {
        //collect user principals and credentials in a gui specific manner
        //such as username/password html form, X509 certificate, OpenID, etc.
        //We'll use the username/password example here since it is the most common.
        UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
        //this is all you have to do to support 'remember me' (no config - built in!):
        token.setRememberMe(true);
        currentUser.login(token);
    }

      登陆失败的处理:

    try {
        currentUser.login( token );
        //if no exception, that's it, we're done!
    } catch ( UnknownAccountException uae ) {
        //username wasn't in the system, show them an error message?
    } catch ( IncorrectCredentialsException ice ) {
        //password didn't match, try again?
    } catch ( LockedAccountException lae ) {
        //account for that username is locked - can't login.  Show them a message?
    }
        ... more types exceptions to check if you want ...
    } catch ( AuthenticationException ae ) {
        //unexpected condition - error?
    }

      获取登陆用户的信息,比如用户名:

    currentUser.getPrincipal()

      判断登陆用户是否有指定角色或权限:

    if ( currentUser.hasRole( "schwartz" ) ) {
        log.info("May the Schwartz be with you!" );
    } else {
        log.info( "Hello, mere mortal." );
    }
    
    if ( currentUser.isPermitted( "lightsaber:weild" ) ) {
        log.info("You may use a lightsaber ring.  Use it wisely.");
    } else {
        log.info("Sorry, lightsaber rings are for schwartz masters only.");
    }

      用户退出:

    currentUser.logout();

    2、shiro demo: 身份认证使用textRealm  <--返回目录

      依赖:

    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.2.4</version>
    </dependency>
    
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.12</version>
    </dependency>

      

      在classpath新建配置文件shiro.ini

    [users]
    java=123456

      测试类

    package com.oy;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.config.IniSecurityManagerFactory;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.util.Factory;
    
    public class HelleWorld {
    
        public static void main(String[] args) {
            // 读取配置文件,初始化SecurityManager工厂
            Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro.ini");
            // 获取securityManager实例
            SecurityManager securityManager=factory.getInstance();
            // 把securityManager实例绑定到SecurityUtils
            SecurityUtils.setSecurityManager(securityManager);
            // 得到当前执行的用户
            Subject currentUser=SecurityUtils.getSubject();
            // 创建token令牌,用户名/密码
            UsernamePasswordToken token=new UsernamePasswordToken("java", "123456");
            try{
                // 身份认证
                currentUser.login(token);    
                System.out.println("身份认证成功!");
            }catch(AuthenticationException e){
                e.printStackTrace();
                System.out.println("身份认证失败!");
            }
            // 退出
            currentUser.logout();
        }
    }

    3、身份认证使用jdbcRealm  <--返回目录

      依赖:

    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.2.4</version>
    </dependency>
    
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.12</version>
    </dependency>
    
    <dependency>
        <groupId>c3p0</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.1.2</version>
    </dependency>
    
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>
    
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.37</version>
    </dependency>

      数据库:

    CREATE DATABASE IF NOT EXISTS `db_shiro` DEFAULT CHARACTER SET utf8;
    USE `db_shiro`;
    DROP TABLE IF EXISTS `users`;
    
    CREATE TABLE `users` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `userName` varchar(20) DEFAULT NULL,
      `password` varchar(20) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
    
    insert  into `users`(`id`,`userName`,`password`) values (1,'java','123456');

      在classpath新建配置文件jdbc_shiro.ini

    [main]
    jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
    dataSource=com.mchange.v2.c3p0.ComboPooledDataSource
    dataSource.driverClass=com.mysql.jdbc.Driver
    dataSource.jdbcUrl=jdbc:mysql://localhost:3306/db_shiro
    dataSource.user=root
    dataSource.password=123456
    jdbcRealm.dataSource=$dataSource
    securityManager.realms=$jdbcRealm

      测试代码:

    public static void main(String[] args) {
        // 读取配置文件,初始化SecurityManager工厂
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:jdbc_shiro.ini");
        // 获取securityManager实例
        SecurityManager securityManager = factory.getInstance();
        // 把securityManager实例绑定到SecurityUtils
        SecurityUtils.setSecurityManager(securityManager);
        // 得到当前执行的用户
        Subject currentUser = SecurityUtils.getSubject();
        // 创建token令牌,用户名/密码
        UsernamePasswordToken token = new UsernamePasswordToken("java", "123456");
        try {
            // 身份认证
            currentUser.login(token);
            System.out.println("身份认证成功!");
        } catch (AuthenticationException e) {
            e.printStackTrace();
            System.out.println("身份认证失败!");
        }
    
        // 退出
        currentUser.logout();
    }

    4、编程式授权  <--返回目录

      shiro_role.ini

    [users]
    java=123456,role1,role2
    jack=123456,role1

      角色

    @Test
    public void testHasRole() {
        Subject currentUser = ShiroUtils.login("classpath:shiro_role.ini", "java", "123456");
        
        System.out.println(currentUser.hasRole("role1") ? "有role1这个角色" : "没有role1这个角色");
        
        boolean[] results = currentUser.hasRoles(Arrays.asList("role1", "role2", "role3"));
        System.out.println(results[0] ? "有role1这个角色" : "没有role1这个角色");
        System.out.println(results[1] ? "有role2这个角色" : "没有role2这个角色");
        System.out.println(results[2] ? "有role3这个角色" : "没有role3这个角色");
        
        System.out.println(currentUser.hasAllRoles(Arrays.asList("role1", "role2")) ? "role1,role2这两个角色都有"
                : "role1,role2这个两个角色不全有");
    
        currentUser.logout();
    }
    
    @Test
    public void testCheckRole() {
        Subject currentUser = ShiroUtils.login("classpath:shiro_role.ini", "java", "123456");
        
        // checkRole,没有该角色报UnauthorizedException
        currentUser.checkRole("role1");
        currentUser.checkRoles(Arrays.asList("role1", "role2"));
        currentUser.checkRoles("role1", "role2", "role3");
    
        currentUser.logout();
    }

      shiro_permission.ini

    [users]
    java=123456,role1,role2
    jack=123,role1
    [roles]
    role1=user:select
    role2=user:add,user:update,user:delete

      权限

    @Test
    public void testIsPermitted() {
        Subject currentUser = ShiroUtils.login("classpath:shiro_permission.ini", "java", "123456");
    
        System.out.println(currentUser.isPermitted("user:select") ? "有user:select这个权限" : "没有user:select这个权限");
        System.out.println(currentUser.isPermitted("user:update") ? "有user:update这个权限" : "没有user:update这个权限");
        boolean results[] = currentUser.isPermitted("user:select", "user:update", "user:delete");
        System.out.println(results[0] ? "有user:select这个权限" : "没有user:select这个权限");
        System.out.println(results[1] ? "有user:update这个权限" : "没有user:update这个权限");
        System.out.println(results[2] ? "有user:delete这个权限" : "没有user:delete这个权限");
        
        System.out.println(currentUser.isPermittedAll("user:select", "user:update") ? "有user:select,update这两个权限"
                : "user:select,update这两个权限不全有");
    
        currentUser.logout();
    }
    
    @Test
    public void testCheckPermitted() {
        Subject currentUser = ShiroUtils.login("classpath:shiro_permission.ini", "java", "123456");
        
        currentUser.checkPermission("user:select");
        currentUser.checkPermissions("user:select", "user:update", "user:delete");
        currentUser.logout();
    }

      ShiroUtils

    package com.oy.common;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.config.IniSecurityManagerFactory;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.util.Factory;
    
    public class ShiroUtils {
    
        public static Subject login(String configFile, String userName, String password) {
            // 读取配置文件,初始化SecurityManager工厂
            Factory<SecurityManager> factory = new IniSecurityManagerFactory(configFile);
            // 获取securityManager实例
            SecurityManager securityManager = factory.getInstance();
            // 把securityManager实例绑定到SecurityUtils
            SecurityUtils.setSecurityManager(securityManager);
            // 得到当前执行的用户
            Subject currentUser = SecurityUtils.getSubject();
            // 创建token令牌,用户名/密码
            UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
            try {
                // 身份认证
                currentUser.login(token);
                System.out.println("身份认证成功!");
            } catch (AuthenticationException e) {
                e.printStackTrace();
                System.out.println("身份认证失败!");
            }
            return currentUser;
        }
    }

    5、shiro + spring  <--返回目录

      依赖:

    <!-- 添加Servlet支持 -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
    </dependency>
    
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>javax.servlet.jsp-api</artifactId>
        <version>2.3.1</version>
    </dependency>
    
    <!-- 添加jstl支持 -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
    
    <!-- 添加Spring支持 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.1.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>4.1.7.RELEASE</version>
    </dependency>
    <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-tx</artifactId>
         <version>4.1.7.RELEASE</version>
        </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.1.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>4.1.7.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>4.1.7.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>4.1.7.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>4.1.7.RELEASE</version>
    </dependency>
    
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>4.1.7.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>4.1.7.RELEASE</version>
    </dependency>
    
      <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>1.2.3</version>
    </dependency>
    
    
    <!-- 添加日志支持 -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    
    <!-- 添加mybatis支持 -->
     <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.3.0</version>
    </dependency>
    
    <!-- jdbc驱动包  -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.37</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.2.4</version>
    </dependency>
    
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.12</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-web</artifactId>
        <version>1.2.4</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring</artifactId>
        <version>1.2.4</version>
    </dependency>

      web.xml

    <!-- shiro过滤器定义 -->
    <filter>  
        <filter-name>shiroFilter</filter-name>  
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
    <init-param>  
    <!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 -->  
    <param-name>targetFilterLifecycle</param-name>  
    <param-value>true</param-value>  
    </init-param>  
    </filter>  
    <filter-mapping>  
            <filter-name>shiroFilter</filter-name>  
            <url-pattern>/*</url-pattern>  
    </filter-mapping>
    
    
    <!-- Spring配置文件 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <!-- 编码过滤器 -->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <async-supported>true</async-supported>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!-- Spring监听器 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    <!-- 添加对springmvc的支持 -->
    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

      application.xml中shiro相关配置

    <!-- 自定义Realm -->
    <bean id="myRealm" class="com.java1234.realm.MyRealm"/>  
    
    <!-- 安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
      <property name="realm" ref="myRealm"/>  
    </bean>  
    
    <!-- Shiro过滤器 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
        <!-- Shiro的核心安全接口,这个属性是必须的 -->  
        <property name="securityManager" ref="securityManager"/>
        <!-- 身份认证失败,则跳转到登录页面的配置 -->  
        <property name="loginUrl" value="/index.jsp"/>
        <!-- 权限认证失败,则跳转到指定页面 -->  
        <property name="unauthorizedUrl" value="/unauthor.jsp"/>  
        <!-- Shiro连接约束配置,即过滤链的定义 -->  
        <property name="filterChainDefinitions">  
            <value>  
                /login=anon
                /admin*=authc
                /student=roles[teacher]
                /teacher=perms["user:create"]
            </value>  
        </property>
    </bean>  
    
    <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->  
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>  
    
    <!-- 开启Shiro注解 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/>  
        <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">  
      <property name="securityManager" ref="securityManager"/>  
    </bean>  

      自定义Realm

    public class MyRealm extends AuthorizingRealm{
    
        @Resource
        private UserService userService;
        
        /**
         * 验证当前登录的用户
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            String userName=(String)token.getPrincipal();
            User user=userService.getByUserName(userName);
            if(user!=null){
                AuthenticationInfo authcInfo=new SimpleAuthenticationInfo(user.getUserName(),user.getPassword(),"xx");
                return authcInfo;
            }else{
                return null;                
            }
        }
        
        /**
         * 为当限前登录的用户授予角色和权
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            String userName=(String)principals.getPrimaryPrincipal();
            SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();
            authorizationInfo.setRoles(userService.getRoles(userName));
            authorizationInfo.setStringPermissions(userService.getPermissions(userName));
            return authorizationInfo;
        }
    }

      登陆

    /**
     * 用户Controller
     * @author oy
     */
    @Controller
    @RequestMapping("/user")
    public class UserController {
    
        /**
         * 用户登录
         * @param user
         * @param request
         * @return
         */
        @RequestMapping("/login")
        public String login(User user,HttpServletRequest request){
            Subject subject=SecurityUtils.getSubject();
            UsernamePasswordToken token=new UsernamePasswordToken(user.getUserName(), user.getPassword());
            try{
                subject.login(token);
                Session session=subject.getSession();
                System.out.println("sessionId:"+session.getId());
                System.out.println("sessionHost:"+session.getHost());
                System.out.println("sessionTimeout:"+session.getTimeout());
                session.setAttribute("info", "session的数据");
                return "redirect:/success.jsp";
            }catch(Exception e){
                e.printStackTrace();
                request.setAttribute("user", user);
                request.setAttribute("errorMsg", "用户名或密码错误!");
                return "index";
            }
        }
        
    }
  • 相关阅读:
    python 的基础 学习 第六天 基础数据类型的操作方法 字典
    python 的基础 学习 第五天 基础数据类型的操作方法
    python 的基础 学习 第四天 基础数据类型
    ASP.NET MVC 入门8、ModelState与数据验证
    ASP.NET MVC 入门7、Hellper与数据的提交与绑定
    ASP.NET MVC 入门6、TempData
    ASP.NET MVC 入门5、View与ViewData
    ASP.NET MVC 入门4、Controller与Action
    ASP.NET MVC 入门3、Routing
    ASP.NET MVC 入门2、项目的目录结构与核心的DLL
  • 原文地址:https://www.cnblogs.com/xy-ouyang/p/11324657.html
Copyright © 2011-2022 走看看