zoukankan      html  css  js  c++  java
  • shiro高速入门

    第一部分 什么是Apache Shiro



    1、什么是 apache shiro :


    Apache Shiro是一个功能强大且易于使用的Java安全框架,提供了认证。授权。加密。和会话管理

    如同 Spring security 一样都是是一个权限安全框架,可是与Spring Security相比。在于他使用了和比較简洁易懂的认证和授权方式。



    2、Apache Shiro 的三大核心组件:


    1、Subject :当前用户的操作

    2、SecurityManager:用于管理全部的Subject

    3、Realms:用于进行权限信息的验证


    Subject:即当前用户,在权限管理的应用程序里往往须要知道谁可以操作什么,谁拥有操作该程序的权利,shiro中则须要通过Subject来提供基础的当前用户信息,Subject 不只代表某个用户,也可以是第三方进程、后台帐户(Daemon Account)或其它类似事物。

    SecurityManager:即全部Subject的管理者,这是Shiro框架的核心组件,能够把他看做是一个Shiro框架的全局管理组件。用于调度各种Shiro框架的服务。

    Realms:Realms则是用户的信息认证器和用户的权限人证器,我们须要自己来实现Realms来自己定义的管理我们自己系统内部的权限规则。



    3、Authentication 和 Authorization


    在shiro的用户权限认证过程中其通过两个方法来实现:

    1、Authentication:是验证用户身份的过程。

    2、Authorization:是授权訪问控制,用于对用户进行的操作进行人证授权。证明该用户是否同意进行当前操作,如訪问某个链接,某个资源文件等。




    4、其它组件:


    除了以上几个组件外。Shiro还有几个其它组件:

    1、SessionManager :Shiro为不论什么应用提供了一个会话编程范式。

    2、CacheManager :对Shiro的其它组件提供缓存支持。




    5、Shiro 完整架构图: 



    图片转自:http://kdboy.iteye.com/blog/1154644



    第二部分 Apache Shiro 整合Spring的Web程序构建


    1、准备工具:


    持久层框架:Hibernate4  这边我使用了Hibernate来对数据持久层进行操作

    控制显示层框架:SpringMVC 这边我使用了SpringMVC实际开发中也能够是其它框架

    数据库:MySql

    准备好所须要的jar放到项目中。

     


    2、创建数据库:



    首先须要四张表,分别为 user(用户)、role(角色)、permission(权限)、userRole(用户角色关系表)

    这边分别创建四张表的实体类,通过Hiberantehibernate.hbm2ddl.auto属性的update 来自己主动生成数据表结构。


    [java] view plain copy
     print?在CODE上查看代码片派生到我的代码片
    1. /*** 
    2.  * 用户表 
    3.  *  
    4.  * @author Swinglife 
    5.  *  
    6.  */  
    7. @Table(name = "t_user")  
    8. @Entity  
    9. public class User {  
    10.   
    11.     @Id  
    12.     @GeneratedValue(strategy = GenerationType.AUTO)  
    13.     Integer id;  
    14.     /** username **/  
    15.     String username;  
    16.     /** password **/  
    17.     String password;  
    18.     /** 是否删除 **/  
    19.     Integer isDelete;  
    20.     /** 创建时间 **/  
    21.     Date createDate;  
    22.     //多对多用户权限表  
    23.     @OneToMany(mappedBy = "user",cascade=CascadeType.ALL)  
    24.     List<UserRole> userRoles;  
    25.   
    26. 省略get set….  
    27.   
    28. }  

    [java] view plain copy
     print?在CODE上查看代码片派生到我的代码片
    1. /**** 
    2.  * 角色表 
    3.  *  
    4.  * @author Swinglife 
    5.  *  
    6.  */  
    7. @Entity  
    8. @Table(name = "t_role")  
    9. public class Role {  
    10.     @Id  
    11.     @GeneratedValue(strategy = GenerationType.AUTO)  
    12.     Integer id;  
    13.     /**角色名**/  
    14.     String name;  
    15.     /**角色说明**/  
    16.     String description;  
    17.   
    18.   
    19. }  

    [java] view plain copy
     print?在CODE上查看代码片派生到我的代码片
    1. /**** 
    2.  * 权限表 
    3.  *  
    4.  * @author Swinglife 
    5.  *  
    6.  */  
    7. @Entity  
    8. @Table(name = "t_permission")  
    9. public class Permission {  
    10.   
    11.     @Id  
    12.     @GeneratedValue(strategy = GenerationType.AUTO)  
    13.     Integer id;  
    14.     /**token**/  
    15.     String token;  
    16.     /**资源url**/  
    17.     String url;  
    18.     /**权限说明**/  
    19.     String description;  
    20.     /**所属角色编号**/  
    21.     Integer roleId;  
    22.   
    23. }  

    [java] view plain copy
     print?

    在CODE上查看代码片派生到我的代码片

    1. /*** 
    2.  * 用户角色表 
    3.  *  
    4.  * @author Swinglife 
    5.  *  
    6.  */  
    7. @Entity  
    8. @Table(name = "t_user_role")  
    9. public class UserRole {  
    10.   
    11.     @Id  
    12.     @GeneratedValue(strategy = GenerationType.AUTO)  
    13.     Integer id;  
    14.   
    15.     @ManyToOne(cascade = CascadeType.ALL)  
    16.     @JoinColumn(name = "userId", unique = true)  
    17.     User user;  
    18.     @ManyToOne  
    19.     @JoinColumn(name = "roleId", unique = true)  
    20.     Role role;  
    21.   
    22. }  

    3、编写操作用户业务的Service:


    [java] view plain copy
     print?

    在CODE上查看代码片派生到我的代码片

    1. @Service  
    2. public class AccountService {  
    3.   
    4.     /**** 
    5.      * 通过username获取用户对象 
    6.      *  
    7.      * @param username 
    8.      * @return 
    9.      */  
    10.     public User getUserByUserName(String username) {  
    11.         User user = (User) dao.findObjectByHQL("FROM User WHERE username = ?

      "new Object[] { username });  

    12.         return user;  
    13.     }  
    14.   
    15.     /*** 
    16.      * 通过username获取权限资源 
    17.      *  
    18.      * @param username 
    19.      * @return 
    20.      */  
    21.     public List<String> getPermissionsByUserName(String username) {  
    22.         System.out.println("调用");  
    23.         User user = getUserByUserName(username);  
    24.         if (user == null) {  
    25.             return null;  
    26.         }  
    27.         List<String> list = new ArrayList<String>();  
    28.         // System.out.println(user.getUserRoles().get(0).get);  
    29.         for (UserRole userRole : user.getUserRoles()) {  
    30.             Role role = userRole.getRole();  
    31.             List<Permission> permissions = dao.findAllByHQL("FROM Permission WHERE roleId = ?"new Object[] { role.getId() });  
    32.             for (Permission p : permissions) {  
    33.                 list.add(p.getUrl());  
    34.             }  
    35.         }  
    36.         return list;  
    37.     }  
    38.   
    39.     // 公共的数据库訪问接口  
    40.     // 这里省略BaseDao dao的编写  
    41.     @Autowired  
    42.     private BaseDao dao;  
    43. }  



    4、编写shiro组件自己定义Realm:


    [java] view plain copy
     print?

    在CODE上查看代码片派生到我的代码片

    1. package org.swinglife.shiro;  
    2.   
    3. import java.util.List;  
    4.   
    5. import org.apache.shiro.authc.AuthenticationException;  
    6. import org.apache.shiro.authc.AuthenticationInfo;  
    7. import org.apache.shiro.authc.AuthenticationToken;  
    8. import org.apache.shiro.authc.SimpleAuthenticationInfo;  
    9. import org.apache.shiro.authc.UsernamePasswordToken;  
    10. import org.apache.shiro.authz.AuthorizationInfo;  
    11. import org.apache.shiro.authz.SimpleAuthorizationInfo;  
    12. import org.apache.shiro.realm.AuthorizingRealm;  
    13. import org.apache.shiro.subject.PrincipalCollection;  
    14. import org.swinglife.model.User;  
    15. import org.swinglife.service.AccountService;  
    16.   
    17. /**** 
    18.  * 自己定义Realm 
    19.  *  
    20.  * @author Swinglife 
    21.  *  
    22.  */  
    23. public class MyShiroRealm extends AuthorizingRealm {  
    24.   
    25.     /*** 
    26.      * 获取授权信息 
    27.      */  
    28.     @Override  
    29.     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) {  
    30.         //依据自己系统规则的须要编写获取授权信息,这里为了高速入门仅仅获取了用户相应角色的资源url信息  
    31.         String username = (String) pc.fromRealm(getName()).iterator().next();  
    32.         if (username != null) {  
    33.             List<String> pers = accountService.getPermissionsByUserName(username);  
    34.             if (pers != null && !pers.isEmpty()) {  
    35.                 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();  
    36.                 for (String each : pers) {  
    37.                     //将权限资源加入到用户信息中  
    38.                     info.addStringPermission(each);  
    39.                 }  
    40.                 return info;  
    41.             }  
    42.         }  
    43.         return null;  
    44.     }  
    45.     /*** 
    46.      * 获取认证信息 
    47.      */  
    48.     @Override  
    49.     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken at) throws AuthenticationException {  
    50.         UsernamePasswordToken token = (UsernamePasswordToken) at;  
    51.         // 通过表单接收的username  
    52.         String username = token.getUsername();  
    53.         if (username != null && !"".equals(username)) {  
    54.             User user = accountService.getUserByUserName(username);  
    55.             if (user != null) {  
    56.                 return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());  
    57.             }  
    58.         }  
    59.   
    60.         return null;  
    61.     }  
    62.       
    63.     /**用户的业务类**/  
    64.     private AccountService accountService;  
    65.       
    66.     public AccountService getAccountService() {  
    67.         return accountService;  
    68.     }  
    69.   
    70.     public void setAccountService(AccountService accountService) {  
    71.         this.accountService = accountService;  
    72.     }  
    73.   
    74. }  

    上述类继承了Shiro的AuthorizingRealm类 实现了AuthorizationInfoAuthenticationInfo两个方法,用于获取用户权限和认证用户登录信息


    5、编写LoginController:



    [java] view plain copy
     print?在CODE上查看代码片派生到我的代码片
    1. package org.swinglife.controller;  
    2.   
    3. import org.apache.shiro.SecurityUtils;  
    4. import org.apache.shiro.authc.UsernamePasswordToken;  
    5. import org.apache.shiro.subject.Subject;  
    6. import org.springframework.beans.factory.annotation.Autowired;  
    7. import org.springframework.stereotype.Controller;  
    8. import org.springframework.web.bind.annotation.RequestMapping;  
    9. import org.springframework.web.bind.annotation.RequestMethod;  
    10. import org.springframework.web.portlet.ModelAndView;  
    11. import org.swinglife.model.User;  
    12. import org.swinglife.service.AccountService;  
    13.   
    14. /**** 
    15.  * 用户登录Controller 
    16.  *  
    17.  * @author Swinglife 
    18.  *  
    19.  */  
    20. @Controller  
    21. public class LoginController {  
    22.   
    23.     /*** 
    24.      * 跳转到登录页面 
    25.      *  
    26.      * @return 
    27.      */  
    28.     @RequestMapping(value = "toLogin")  
    29.     public String toLogin() {  
    30.         // 跳转到/page/login.jsp页面  
    31.         return "login";  
    32.     }  
    33.   
    34.     /*** 
    35.      * 实现用户登录 
    36.      *  
    37.      * @param username 
    38.      * @param password 
    39.      * @return 
    40.      */  
    41.     @RequestMapping(value = "login")  
    42.     public ModelAndView Login(String username, String password) {  
    43.         ModelAndView mav = new ModelAndView();  
    44.         User user = accountService.getUserByUserName(username);  
    45.         if (user == null) {  
    46.             mav.setView("toLogin");  
    47.             mav.addObject("msg""用户不存在");  
    48.             return mav;  
    49.         }  
    50.         if (!user.getPassword().equals(password)) {  
    51.             mav.setView("toLogin");  
    52.             mav.addObject("msg""账号password错误");  
    53.             return mav;  
    54.         }  
    55.         SecurityUtils.getSecurityManager().logout(SecurityUtils.getSubject());  
    56.         // 登录后存放进shiro token  
    57.         UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());  
    58.         Subject subject = SecurityUtils.getSubject();  
    59.         subject.login(token);  
    60.         // 登录成功后会跳转到successUrl配置的链接,不用管以下返回的链接。  
    61.         mav.setView("redirect:/home");  
    62.         return mav;  
    63.     }  
    64.   
    65.     // 处理用户业务类  
    66.     @Autowired  
    67.     private AccountService accountService;  
    68. }  


    6、编写信息认证成功后的跳转页面:


    [java] view plain copy
     print?在CODE上查看代码片派生到我的代码片
    1. package org.swinglife.controller;  
    2.   
    3. import org.springframework.stereotype.Controller;  
    4. import org.springframework.web.bind.annotation.RequestMapping;  
    5.   
    6. @Controller  
    7. public class IndexController {  
    8.   
    9.     @RequestMapping("home")  
    10.     public String index() {  
    11.         System.out.println("登录成功");  
    12.         return "home";  
    13.     }  
    14. }  


    7、Shiro的配置文件.xml


    [java] view plain copy
     print?在CODE上查看代码片派生到我的代码片
    1. <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
    2.         <property name="securityManager" ref="securityManager" />  
    3.         <property name="loginUrl" value="/toLogin" />  
    4.         <property name="successUrl" value="/home" />  
    5.         <property name="unauthorizedUrl" value="/403" />  
    6.            
    7.         <property name="filterChainDefinitions">  
    8.             <value>  
    9.                 /toLogin = authc <!-- authc 表示须要认证才干訪问的页面 -->  
    10.                 /home = authc, perms[/home]  <!-- perms 表示须要该权限才干訪问的页面 -->  
    11.             </value>  
    12.         </property>  
    13.     </bean>  
    14.   
    15.   
    16.   
    17.   
    18.     <bean id="myShiroRealm" class="org.swinglife.shiro.MyShiroRealm">  
    19.         <property name="accountService" ref="accountService" />  
    20.     </bean>  
    21.   
    22.     <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
    23.         <property name="realm" ref="myShiroRealm"></property>  
    24.     </bean>  
    25.   
    26.     <bean id="accountService" class="org.swinglife.service.AccountService"></bean>  
    27.   
    28.     <!-- <bean id="shiroCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">   
    29.         <property name="cacheManager" ref="cacheManager" /> </bean> -->  



    loginUrl 用于配置登陆页

    successUrl 用于配置登录成功后返回的页面。只是该參数仅仅会在当登录页面中并没有不论什么返回页面时才会生效。否则会跳转到登录Controller中的指定页面。

    unauthorizedUrl 用于配置没有权限訪问页面时跳转的页面


    filterChainDefinitions:apache shiro通过filterChainDefinitions參数来分配链接的过滤,资源过滤有经常使用的下面几个參数:

    1、authc 表示须要认证的链接

    2、perms[/url] 表示该链接须要拥有相应的资源/权限才干訪问

    3、roles[admin] 表示须要相应的角色才干訪问

    4、perms[admin:url] 表示须要相应角色的资源才干訪问


    8、登陆页login.jsp

    [html] view plain copy
     print?在CODE上查看代码片派生到我的代码片
    1. <body>  
    2.   
    3. <h1>user login</h1>  
    4. <form action="login" method="post">  
    5. username:<input type="text" name="username"><p>  
    6. password:<input type="password" name="password">  
    7. <p>  
    8. ${msg }  
    9. <input type="submit" value="submit">  
    10. </form>  
    11. </body>  




    9、执行程序

    在数据库中加入一条用户、角色、以及权限数据,而且在关联表中加入一条关联数据:








    在浏览器中訪问: home页面 就会跳转到登录页面:  




    最后输入 账号password 就会跳转到登录成功页面。


    shiro jar:http://download.csdn.net/detail/swingpyzf/8766673

  • 相关阅读:
    网络协议 22
    网络协议 21
    网络协议 20
    网络协议 19
    网络协议 18
    网络协议 17
    网络协议 16
    网络协议 15
    网络协议 14
    .net 4.0 中的特性总结(五):并行编程
  • 原文地址:https://www.cnblogs.com/wgwyanfs/p/7291613.html
Copyright © 2011-2022 走看看