什么是shiro?

Shiro是apache旗下一个开源框架,它将软件系统的安全认证相关的功能抽取出来,实现用户身份认证,权限授权、加密、会话管理等功能,组成了一个通用的安全认证框架。

 

为什么要用shiro?

既然可以基于url实现权限的管理,为什么还要用shiro呢??

1.shiro将安全认证相关的功能抽取出来组成一个框架,使用shiro就可以非常快速的完成认证、授权等功能的开发,降低系统成本。最主要的就是方便了我们的开发。

2.shiro使用广泛,shiro可以运行在web应用,非web应用,集群分布式应用中越来越多的用户开始使用shiro。

 

shiro认证

认证流程:

微服务下的认证授权 微服务shiro认证_数据库

 

实例:

1.创建一个Java工程,并加入shiro-core的jar包以及它的依赖包。

微服务下的认证授权 微服务shiro认证_java_02

 

2.自定义realm

Shiro有自带的IniRealm,IniRealm从ini配置文件中读取用户的信息,大部分情况下需要从系统的数据库中读取用户信息,所以需要自定义realm。

 



[java]  view plain  copy

    1. public class CustomRealm extends AuthorizingRealm {  
    2.   
    3. @Override  
    4. public String getName() {  
    5. return "customRealm";  
    6.     }  
    7.   
    8. // 用于认证  
    9. @Override  
    10. protected AuthenticationInfo doGetAuthenticationInfo(  
    11. throws AuthenticationException {  
    12.   
    13. // token是用户输入的  
    14. // 第一步从token中取出身份信息  
    15.         String userCode = (String) token.getPrincipal();  
    16.   
    17. // 第二步:根据用户输入的userCode从数据库中查询  
    18. // 模拟从数据库查询到密码  
    19. "111111";  
    20.   
    21. // 如果查询到返回认证信息AuthenticationInfo  
    22.   
    23. new SimpleAuthenticationInfo(  
    24. this.getName());  
    25. return simpleAuthenticationInfo;  
    26.     }  
    27. }



     

    3.配置shiro-realm.ini文件


    微服务下的认证授权 微服务shiro认证_ci_03



    [html]  view plain  copy

    1. [main]  
    2. #自定义realm  
    3. customRealm=cn.itcast.shiro.realm.CustomRealm  
    4. #将realm设置到securityManager,相当于spring中注入  
    5. securityManager.realms=$customRealm


    4.创建认证代码



    [java]  view plain  copy

    1. // 用户登录和退出  
    2. @Test  
    3. public void testCustomRealm() {  
    4.   
    5. // 创建securityManager工厂,通过ini配置文件创建securityManager工厂  
    6. new IniSecurityManagerFactory(  
    7. "classpath:shiro-realm.ini");  
    8.   
    9. // 通过工厂创建SecurityManager  
    10.     SecurityManager securityManager = factory.getInstance();  
    11.   
    12. // 将securityManager设置到运行环境中  
    13.     SecurityUtils.setSecurityManager(securityManager);  
    14.   
    15. // 创建一个Subject实例,该实例认证要使用上边创建的securityManager进行  
    16.     Subject subject = SecurityUtils.getSubject();  
    17.   
    18. // 创建token令牌,记录用户认证的身份和凭证即账号和密码  
    19. new UsernamePasswordToken("zhangsan",  
    20. "111111");  
    21.   
    22. try {  
    23. // 用户登陆  
    24.         subject.login(token);  
    25. catch (AuthenticationException e) {  
    26. // TODO Auto-generated catch block  
    27.         e.printStackTrace();  
    28.     }  
    29.   
    30. // 用户认证状态  
    31.   
    32.     Boolean isAuthenticated = subject.isAuthenticated();  
    33.   
    34. "用户认证状态:" + isAuthenticated);  
    35.   
    36. // 用户退出  
    37.   
    38.     subject.logout();  
    39.   
    40.     isAuthenticated = subject.isAuthenticated();  
    41.   
    42. "用户认证状态:" + isAuthenticated);  
    43.   
    44. }



    5.认证流程

    (1)创建token令牌,token中有用户提交的认证信息即账号和密码

    (2)执行subject.login(token),最终由securityManager通过Authenticator进行认证

    (3)Authenticator的实现ModularRealmAuthenticator调用realm从数据库中取用户真实的账号和密码

    (4)CustomRealm先根据token中的账号去数据库中找该账号,如果找不到则给ModularRealmAuthenticator返回null,如果找到则匹配密码,匹配密码成功则认证通过。

    6.测试


    微服务下的认证授权 微服务shiro认证_ci_04

    登录时用户认证成功,退出时用户认证失败。

     

    shiro授权

    授权流程

    微服务下的认证授权 微服务shiro认证_微服务下的认证授权_05

     

    授权方式

    shiro支持三种方式的授权:

    1.编程式



    [java]  view plain  copy

    1. Subject subject = SecurityUtils.getSubject();  
    2. if(subject.hasPermission(“admin”)) {  
    3. //有权限  
    4. } else {  
    5. //无权限  
    6. }



    2.注解式



    [java]  view plain  copy

    1. @RequiresPermissions("admin")  
    2. public void hello() {  
    3. //有权限  
    4. }


    3.JSP/GSP标签



    [java]  view plain  copy

    1. <shiro:hasPermission name="admin">  
    2. <!— 有权限—>  
    3. </shiro:hasRole>



    在web系统集成中使用后两种方式,我在这儿举个简单的例子就用第一种方式了。

    实例

    1.自定义realm



    [java]  view plain  copy

    1. // 用于授权  
    2. @Override  
    3. protected AuthorizationInfo doGetAuthorizationInfo(  
    4.         PrincipalCollection principals) {  
    5. // 获取身份信息  
    6. //将getPrimaryPrincipal方法返回值转为真实身份类型(在上边的doGetAuthenticationInfo认证通过填充到Simpl)  
    7.     String username = (String) principals.getPrimaryPrincipal();  
    8.       
    9. // 根据身份信息从数据库中查询权限数据  
    10. // ....这里使用静态数据模拟  
    11. new ArrayList<String>();  
    12. "user:create");  
    13. "user:delete");  
    14.   
    15. // 将权限信息封闭为AuthorizationInfo  
    16. new SimpleAuthorizationInfo();  
    17. for (String permission : permissions) {  
    18.         simpleAuthorizationInfo.addStringPermission(permission);  
    19.     }  
    20.   
    21. return simpleAuthorizationInfo;  
    22.   
    23. }



    2.配置shiro-realm.ini文件与上面认证配置文件相同

    3.创建授权代码



    [java]  view plain  copy

    1. // 自定义realm进行资源授权测试  
    2. @Test  
    3. public void testAuthorizationCustomRealm() {  
    4.   
    5. // 从ini文件中创建SecurityManager工厂  
    6. new IniSecurityManagerFactory(  
    7. "classpath:shiro-realm.ini");  
    8.   
    9. // 创建SecurityManager  
    10.     SecurityManager securityManager = factory.getInstance();  
    11.   
    12. // 将securityManager设置到运行环境  
    13.     SecurityUtils.setSecurityManager(securityManager);  
    14.   
    15. // 创建主体对象  
    16.     Subject subject = SecurityUtils.getSubject();  
    17.   
    18. // 对主体对象进行认证  
    19. // 用户登陆  
    20. // 设置用户认证的身份(principals)和凭证(credentials)  
    21. new UsernamePasswordToken("zhangsan",  
    22. "111111");  
    23. try {  
    24.         subject.login(token);  
    25. catch (AuthenticationException e) {  
    26. // TODO Auto-generated catch block  
    27.         e.printStackTrace();  
    28.     }  
    29.   
    30. // 用户认证状态  
    31.     Boolean isAuthenticated = subject.isAuthenticated();  
    32.   
    33. "用户认证状态:" + isAuthenticated);  
    34.   
    35. // 授权检测,失败则抛出异常  
    36. // subject.checkRole("role22");  
    37.   
    38. // 基于资源授权  
    39. "是否拥有某一个权限:" + subject.isPermitted("user:delete"));  
    40. "是否拥有多个权限:"  
    41. "user:update", "user:delete"));  
    42.   
    43. // 检查权限  
    44. "user:delete");  
    45.   
    46. }



    4.授权流程

    (1)执行subject.isPermitted("user:delete")

    (2)securityManager通过ModularRealmAuthorizer进行授权

    (3)ModularRealmAuthorizer调用realm获取权限信息

    (4)ModularRealmAuthorizer再通过permissionResolver解析权限字符串,校验是否匹配

    5.测试

    微服务下的认证授权 微服务shiro认证_ci_06

    表明该用户拥有delete权限但是不拥有update权限。