MyException - 我的异常网
当前位置:我的异常网» Apache » Apache Shiro 高速入门教程,shiro 基础教程

Apache Shiro 高速入门教程,shiro 基础教程

www.MyException.Cn  网友分享于:2013-10-11  浏览:0次
Apache Shiro 快速入门教程,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(用户角色关系表)

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

 

 

[java] view plain copy
 
 print?
  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.     /** 用户名 **/  
  15.     String username;  
  16.     /** 密码 **/  
  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?
  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?
  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?
  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?
  1. @Service  
  2. public class AccountService {  
  3.   
  4.     /**** 
  5.      * 通过用户名获取用户对象 
  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.      * 通过用户名获取权限资源 
  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?
  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.         // 通过表单接收的用户名  
  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类 实现了AuthorizationInfo和AuthenticationInfo两个方法,用于获取用户权限和认证用户登录信息

 

 

5、编写LoginController:

 

 

 

 

[java] view plain copy
 
 print?
  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", "账号密码错误");  
  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?
  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?
  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?
  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页面 就会跳转到登录页面:  


 

 

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

 

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

项目源码:github:https://github.com/swinglife/shiro_ex

 

文章评论

不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
我的丈夫是个程序员
我的丈夫是个程序员
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
编程语言是女人
编程语言是女人
旅行,写作,编程
旅行,写作,编程
总结2014中国互联网十大段子
总结2014中国互联网十大段子
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
漫画:程序员的工作
漫画:程序员的工作
老程序员的下场
老程序员的下场
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
每天工作4小时的程序员
每天工作4小时的程序员
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
程序员的鄙视链
程序员的鄙视链
鲜为人知的编程真相
鲜为人知的编程真相
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
那些争议最大的编程观点
那些争议最大的编程观点
10个调试和排错的小建议
10个调试和排错的小建议
代码女神横空出世
代码女神横空出世
为什么程序员都是夜猫子
为什么程序员都是夜猫子
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
中美印日四国程序员比较
中美印日四国程序员比较
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
程序员必看的十大电影
程序员必看的十大电影
程序员和编码员之间的区别
程序员和编码员之间的区别
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
 程序员的样子
程序员的样子
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
如何成为一名黑客
如何成为一名黑客
我是如何打败拖延症的
我是如何打败拖延症的
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
Java程序员必看电影
Java程序员必看电影
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
程序员应该关注的一些事儿
程序员应该关注的一些事儿
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有