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";
            }
        }
        
    }
  • 相关阅读:
    vSphere笔记01~02
    【科普】人眼到底等于多少像素
    《标题党》自我修炼的10个秘籍
    说说云盘背后的黑科技!
    用shell批量编码转换
    Java课设--俄罗斯方块Tetris
    教程,Python图片转字符堆叠图
    谈谈索引的哲学思想
    MySQL索引实战经验总结
    博客要转型啦
  • 原文地址:https://www.cnblogs.com/xy-ouyang/p/11324657.html
Copyright © 2011-2022 走看看