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. *@authorSwinglife

  5. *

  6. */

  7. @Table(name=“t_user”)

  8. @Entity

  9. publicclassUser{

  10. @Id

  11. @GeneratedValue(strategy=GenerationType.AUTO)

  12. Integerid;

  13. /**用户名**/

  14. Stringusername;

  15. /**密码**/

  16. Stringpassword;

  17. /**是否删除**/

  18. IntegerisDelete;

  19. /**创建时间**/

  20. DatecreateDate;

  21. //多对多用户权限表

  22. @OneToMany(mappedBy=“user”,cascade=CascadeType.ALL)

  23. ListuserRoles;

  24. 省略getset….

  25. }

[java] view plain copy print ?

  1. /****

  2. *角色表

  3. *

  4. *@authorSwinglife

  5. *

  6. */

  7. @Entity

  8. @Table(name=“t_role”)

  9. publicclassRole{

  10. @Id

  11. @GeneratedValue(strategy=GenerationType.AUTO)

  12. Integerid;

  13. /**角色名**/

  14. Stringname;

  15. /**角色说明**/

  16. Stringdescription;

  17. }

[java] view plain copy print ?

  1. /****

  2. *权限表

  3. *

  4. *@authorSwinglife

  5. *

  6. */

  7. @Entity

  8. @Table(name=“t_permission”)

  9. publicclassPermission{

  10. @Id

  11. @GeneratedValue(strategy=GenerationType.AUTO)

  12. Integerid;

  13. /**token**/

  14. Stringtoken;

  15. /**资源url**/

  16. Stringurl;

  17. /**权限说明**/

  18. Stringdescription;

  19. /**所属角色编号**/

  20. IntegerroleId;

  21. }

[java] view plain copy print ?

  1. /***

  2. *用户角色表

  3. *

  4. *@authorSwinglife

  5. *

  6. */

  7. @Entity

  8. @Table(name=“t_user_role”)

  9. publicclassUserRole{

  10. @Id

  11. @GeneratedValue(strategy=GenerationType.AUTO)

  12. Integerid;

  13. @ManyToOne(cascade=CascadeType.ALL)

  14. @JoinColumn(name=“userId”,unique=true)

  15. Useruser;

  16. @ManyToOne

  17. @JoinColumn(name=“roleId”,unique=true)

  18. Rolerole;

  19. }

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

[java] view plain copy print ?

  1. @Service

  2. publicclassAccountService{

  3. /****

  4. *通过用户名获取用户对象

  5. *

  6. *@paramusername

  7. *@return

  8. */

  9. publicUsergetUserByUserName(Stringusername){

  10. Useruser=(User)dao.findObjectByHQL(“FROMUserWHEREusername=”,newObject[]{username});

  11. returnuser;

  12. }

  13. /***

  14. *通过用户名获取权限资源

  15. *

  16. *@paramusername

  17. *@return

  18. */

  19. publicListgetPermissionsByUserName(Stringusername){

  20. System.out.println(“调用”);

  21. Useruser=getUserByUserName(username);

  22. if(user==null){

  23. returnnull;

  24. }

  25. Listlist=newArrayList();

  26. //System.out.println(user.getUserRoles().get(0).get);

  27. for(UserRoleuserRole:user.getUserRoles()){

  28. Rolerole=userRole.getRole();

  29. Listpermissions=dao.findAllByHQL(“FROMPermissionWHEREroleId=”,newObject[]{role.getId()});

  30. for(Permissionp:permissions){

  31. list.add(p.getUrl());

  32. }

  33. }

  34. returnlist;

  35. }

  36. //公共的数据库访问接口

  37. //这里省略BaseDaodao的编写

  38. @Autowired

  39. privateBaseDaodao;

  40. }

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

[java] view plain copy print ?

  1. packageorg.swinglife.shiro;

  2. importjava.util.List;

  3. importorg.apache.shiro.authc.AuthenticationException;

  4. importorg.apache.shiro.authc.AuthenticationInfo;

  5. importorg.apache.shiro.authc.AuthenticationToken;

  6. importorg.apache.shiro.authc.SimpleAuthenticationInfo;

  7. importorg.apache.shiro.authc.UsernamePasswordToken;

  8. importorg.apache.shiro.authz.AuthorizationInfo;

  9. importorg.apache.shiro.authz.SimpleAuthorizationInfo;

  10. importorg.apache.shiro.realm.AuthorizingRealm;

  11. importorg.apache.shiro.subject.PrincipalCollection;

  12. importorg.swinglife.model.User;

  13. importorg.swinglife.service.AccountService;

  14. /****

  15. *自定义Realm

  16. *

  17. *@authorSwinglife

  18. *

  19. */

  20. publicclassMyShiroRealmextendsAuthorizingRealm{

  21. /***

  22. *获取授权信息

  23. */

  24. @Override

  25. protectedAuthorizationInfodoGetAuthorizationInfo(PrincipalCollectionpc){

  26. //根据自己系统规则的需要编写获取授权信息,这里为了快速入门只获取了用户对应角色的资源url信息

  27. Stringusername=(String)pc.fromRealm(getName()).iterator().next();

  28. if(username!=null){

  29. Listpers=accountService.getPermissionsByUserName(username);

  30. if(pers!=null&&!pers.isEmpty()){

  31. SimpleAuthorizationInfoinfo=newSimpleAuthorizationInfo();

  32. for(Stringeach:pers){

  33. //将权限资源添加到用户信息中

  34. info.addStringPermission(each);

  35. }

  36. returninfo;

  37. }

  38. }

  39. returnnull;

  40. }

  41. /***

  42. *获取认证信息

  43. */

  44. @Override

  45. protectedAuthenticationInfodoGetAuthenticationInfo(AuthenticationTokenat)throwsAuthenticationException{

  46. UsernamePasswordTokentoken=(UsernamePasswordToken)at;

  47. //通过表单接收的用户名

  48. Stringusername=token.getUsername();

  49. if(username!=null&&!“”.equals(username)){

  50. Useruser=accountService.getUserByUserName(username);

  51. if(user!=null){

  52. returnnewSimpleAuthenticationInfo(user.getUsername(),user.getPassword(),getName());

  53. }

  54. }

  55. returnnull;

  56. }

  57. /**用户的业务类**/

  58. privateAccountServiceaccountService;

  59. publicAccountServicegetAccountService(){

  60. returnaccountService;

  61. }

  62. publicvoidsetAccountService(AccountServiceaccountService){

  63. this.accountService=accountService;

  64. }

  65. }

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

5、编写LoginController:

[java] view plain copy print ?

  1. packageorg.swinglife.controller;

  2. importorg.apache.shiro.SecurityUtils;

  3. importorg.apache.shiro.authc.UsernamePasswordToken;

  4. importorg.apache.shiro.subject.Subject;

  5. importorg.springframework.beans.factory.annotation.Autowired;

  6. importorg.springframework.stereotype.Controller;

  7. importorg.springframework.web.bind.annotation.RequestMapping;

  8. importorg.springframework.web.bind.annotation.RequestMethod;

  9. importorg.springframework.web.portlet.ModelAndView;

  10. importorg.swinglife.model.User;

  11. importorg.swinglife.service.AccountService;

  12. /****

  13. *用户登录Controller

  14. *

  15. *@authorSwinglife

  16. *

  17. */

  18. @Controller

  19. publicclassLoginController{

  20. /***

  21. *跳转到登录页面

  22. *

  23. *@return

  24. */

  25. @RequestMapping(value=“toLogin”)

  26. publicStringtoLogin(){

  27. //跳转到/page/login.jsp页面

  28. return"login";

  29. }

  30. /***

  31. *实现用户登录

  32. *

  33. *@paramusername

  34. *@parampassword

  35. *@return

  36. */

  37. @RequestMapping(value=“login”)

  38. publicModelAndViewLogin(Stringusername,Stringpassword){

  39. ModelAndViewmav=newModelAndView();

  40. Useruser=accountService.getUserByUserName(username);

  41. if(user==null){

  42. mav.setView(“toLogin”);

  43. mav.addObject(“msg”,“用户不存在”);

  44. returnmav;

  45. }

  46. if(!user.getPassword().equals(password)){

  47. mav.setView(“toLogin”);

  48. mav.addObject(“msg”,“账号密码错误”);

  49. returnmav;

  50. }

  51. SecurityUtils.getSecurityManager().logout(SecurityUtils.getSubject());

  52. //登录后存放进shirotoken

  53. UsernamePasswordTokentoken=newUsernamePasswordToken(user.getUsername(),user.getPassword());

  54. Subjectsubject=SecurityUtils.getSubject();

  55. subject.login(token);

  56. //登录成功后会跳转到successUrl配置的链接,不用管下面返回的链接。

  57. mav.setView(“redirect:/home”);

  58. returnmav;

  59. }

  60. //处理用户业务类

  61. @Autowired

  62. privateAccountServiceaccountService;

  63. }

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

[java] view plain copy print ?

  1. packageorg.swinglife.controller;

  2. importorg.springframework.stereotype.Controller;

  3. importorg.springframework.web.bind.annotation.RequestMapping;

  4. @Controller

  5. publicclassIndexController{

  6. @RequestMapping(“home”)

  7. publicStringindex(){

  8. System.out.println(“登录成功”);

  9. return"home";

  10. }

  11. }

7、Shiro的配置文件.xml

[java] view plain copy print ?

  1. <beanid="shiroFilter"class=“org.apache.shiro.spring.web.ShiroFilterFactoryBean”>

  2. <propertyname="securityManager"ref=“securityManager”/>

  3. <propertyname=“loginUrl"value=”/toLogin"/>

  4. <propertyname=“successUrl"value=”/home"/>

  5. <propertyname=“unauthorizedUrl"value=”/403"/>

  6. <propertyname=“filterChainDefinitions”>

  7. /toLogin=authc

  8. /home=authc,perms[/home]

  9. <beanid="myShiroRealm"class=“org.swinglife.shiro.MyShiroRealm”>

  10. <propertyname="accountService"ref=“accountService”/>

  11. <beanid="securityManager"class=“org.apache.shiro.web.mgt.DefaultWebSecurityManager”>

  12. <propertyname="realm"ref=“myShiroRealm”>

  13. <beanid="accountService"class=“org.swinglife.service.AccountService”>

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. <h1>userlogin</h1>

  3. <formaction="login"method=“post”>

  4. username:<inputtype="text"name=“username”><p>

  5. password:<inputtype="password"name=“password”>

  6. <p>

  7. ${msg}

  8. <inputtype="submit"value=“submit”>

  9. </form>

  10. </body>

9、运行程序

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

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

转载出处:

最后输入 账号密码 就会跳转

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

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值