美文网首页
Apache Shiro -- 安全

Apache Shiro -- 安全

作者: saoraozhe3hao | 来源:发表于2018-09-06 17:55 被阅读0次

官网:http://shiro.apache.org/

概念
认证:即登录
授权:即允许某种操作
会话:即保持已登录状态

与Spring Security的比较:Shiro 较简单灵活,可以脱离Spring,权限控制粒度较粗

层次关系

Shiro操作类(SecurityUtils)-> 安全管理器(Security Manager)、实体(Subject)
安全管理器 -> 认证器(Authenticator,即登录)、授权器(Authorizer)、会话管理器(Session Manager)、缓存管理器(Cache Manager)、Realm(领域)
Realm -> Matcher(密码加密)

Realm:安全管理器与数据存储之间的中介
会话管理 和 缓存管理,Spring Session 和 Spring-data-redis 有更好的实现

一般表结构

1、用户表users(username, password)
2、角色表user_roles(username, role_name),记录用户名 和 角色名的对应关系
3、权限表roles_permission(role_name, permission),记录角色名 和 权限名的关系

Shiro应用组成
1、配置Maven依赖

<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-spring</artifactId>    <!-- 整合Spring 和 Shiro,包含了shrio-core和shiro-web -->
  <version>1.4.0</version>
</dependency>

2、自定义Realm
新建realm包,里面新建MyRealm类

public class MyRealm extends AuthorizingRealm {
    {  // Matcher
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("md5");  // 确定算法
        matcher.setHashIterations(1);  // 确定加密次数
        super.setCredentialsMatcher(matcher);
    } // 初始化块
    // 这个方法用于认证,即subject.login()时调用
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) 
        throws AuthenticationException {  // UsernamePasswordToken 是 AuthenticationToken的子类,这里的入参就是 subject.login()传进来的token
        String username = (String) authenticationToken.getPrincipal();  // 获取首要信息,即UsernamePasswordToken里的username
        String password = getPasswordByUsername(username);  // 从数据库里查询密码
        if(password == null){
            return null;  // 返回null即登录失败
        }
        // 提交的password加密后 和 数据库里的password进行对比
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username, password, "MyRealm");
        authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("salt_1"));  // 加盐,算法为md5($salt.$pass)
        return authenticationInfo;
    }

    // 这个方法用于授权,即获取用户的角色和权限
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String username = (String) principalCollection.getPrimaryPrincipal();
        Set<String> roles = getRolesByUsername(username);  // 查询角色
        Set<String> permissions = getPermissionsByUsername(username); // 查询权限  
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.setRoles(roles);
        authorizationInfo.setStringPermissions(permissions);
        return authorizationInfo;
    }

    private String getPasswordByUsername(String username) {
        return "eafb8cb896588a487ed9679994d25284";  // 这里需要改成访问数据库
    }
    private Set<String> getRolesByUsername(String userName) { // 通过Spring的Service访问数据库
        Set roleSet = new HashSet<String>();
        roleSet.add("role_1");
        roleSet.add("role_2");
        return roleSet;   // 每个需要授权的地方,都会来调用doGetAuthorizationInfo,因此角色和权限信息需要缓存,给Service加上缓存机制即可
    }

    private Set<String> getPermissionsByUsername(String username) { // 这里需要改成访问数据库
        Set permissionSet = new HashSet<String>();
        permissionSet.add("user:delete");
        permissionSet.add("user:update");
        return permissionSet;
    }
}

3、认证与授权

// Security Manager
 MyRealm realm = new MyRealm();
DefaultSecurityManager securityManager = new DefaultSecurityManager();
securityManager.setRealm(realm);
// SecurityUtils
SecurityUtils.setSecurityManager(securityManager);
// Subject
UsernamePasswordToken token = new UsernamePasswordToken("username", "password");
Subject subject = SecurityUtils.getSubject();
subject.login(token);  // token错误,则抛出异常
System.out.println(subject.isAuthenticated());  // 是否已认证
subject.checkRoles("role_1" , "role_2");  // 角色检查失败,则抛出异常
subject.checkPermissions("user:delete", "user:update");  // 检查权限,检查失败则抛出异常
subject.logout();  // 登出
System.out.println(subject.isAuthenticated());

整合Spring

1、配置Maven依赖

<dependency>
    <groupId>org.aspectj</groupId>    <!-- 提供aop:config -->
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.1</version>
</dependency>

2、web.xml中配置过滤器
DelegatingFilterProxy会根据filter-name提交给对应的Bean处理,因此这里的shiroFilter,是Spring配置文件里ShiroFilterFactoryBean的id;此外Spring MVC的springSessionRepositoryFilter不能省

<filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>targetFilterLifecycle</param-name>  <!-- 让Spring容器来调用生命周期函数 -->
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

3、Spring配置文件 applicationContext.xml

<bean name="realm" class="com.hogen.realm.MyRealm"></bean> <!-- 自定义Realm -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="realm" ref="realm"></property>
</bean>
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="securityManager" ref="securityManager"></property>
    <property name="loginUrl" value="/login.html"></property>  <!-- 未认证时访问需要认证的页面或接口,则跳转到login.html -->
    <property name="unauthorizedUrl" value="/403.html"></property>  <!-- 访问无权限的页面或接口,则跳转到403.html -->
    <property name="filterChainDefinitions">
        <!-- 如何校验权限,在这里配置 -->
        <value>
                /login.html = anon       // 无需认证
                /my/login.do = anon
               /my/list.do = roles["role_1"]    // 是某角色
                /my/detail.do = perms["perms_1"]  // 有某权限
                /** = authc                    // 需要认证
        </value>
    </property>
</bean>

4、Spring MVC配置文件 dispatcher-servlet.xml

<aop:config proxy-target-class="true"></aop:config>
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
    <property name="securityManager" ref="securityManager"/>
</bean>
<!-- 捕获Controller抛出的异常 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
        <props>
            <!-- Controller抛出这个异常时,则跳转到 jsp/403.jsp -->
            <prop key="org.apache.shiro.authz.UnauthorizedException">403</prop>
            <!-- Controller抛出这个异常时,则跳转到 jsp/login.jsp -->
            <prop key="org.apache.shiro.authz.UnauthenticatedException">login</prop>
        </props>
    </property>
</bean>

5、Controller

@RequestMapping(value="/login", method=RequestMethod.POST)
@ResponseBody  // 能把这个方法返回的字符串当做响应体返回
public ModelAndView login(){
    Subject subject = SecurityUtils.getSubject();
    UsernamePasswordToken token = new UsernamePasswordToken("username", "password");
    subject.login(token);
    return "success";
}

// 通过了applicationContext.xml中配置的过滤器 shiroFilter后,才会到达这里校验权限
// 权限校验不通过时,则抛出异常,会被dispatcher-servlet.xml配置的SimpleMappingExceptionResolver 捕获
@RequiresRoles({"role_1", "role_2"})  // 是指定角色
@RequiresPermissions("admin")  // 有指定权限
@RequestMapping(value="/list", method=RequestMethod.GET)
@ResponseBody
public String register(){
    return "has permission";
}

相关文章

  • Shiro1-基础知识

    什么是Shiro Apache Shiro 是 Java 的一个安全框架。目前,使用 Apache Shiro 的...

  • Shiro简介

    1、什么是Shiro Apache Shiro是Java的一个安全框架。目前,使用Apache Shiro的人越来...

  • Shiro框架的入门介绍

    什么是Shiro? Apache Shiro是Java的一个安全框架。目前,使用Apache Shiro的人越来越...

  • Shiro和Spring Security对比

    Shiro简介 Apache Shiro是Java的一个安全框架。目前,使用Apache Shiro的人越来越多,...

  • shiro RememeberMe 1.2.4反序列化漏洞

    Shiro简介:shiro(Java安全框架):apache shiro 是一个强大且易用的java安全框架框架,...

  • Shiro

    Shiro(代码) 1.1 简介 Apache Shiro是Java的一个安全框架。目前,使用Apache Shi...

  • Shiro入门

    Shiro 什么是Shiro? Apache Shiro 是一个Java的安全框架。 关于shiro的相关概念: ...

  • Apache Shiro——浅析

    1、什么是 Apache Shiro?Apache Shiro是Java安全框架,其提供认证,授权,加密,和会话管...

  • Spring-Shiro介绍及其使用

    What is Apache Shiro? Apache Shiro是一个功能强大、灵活的,开源的安全框架。它可以...

  • Java 安全框架Apache Shiro学习入门(Shiro

    简介 Apache Shiro 是 Java 的一个安全框架。目前,使用 Apache Shiro 的人越来越多,...

网友评论

      本文标题:Apache Shiro -- 安全

      本文链接:https://www.haomeiwen.com/subject/ipzxgftx.html