易用宝项目记录day5-shiro

易用宝项目记录day5-shiro

1.shiro的认识

  1. shiro是一个权限框架

  2. shiro和Spring security区别

    1. shiro更加易用 属于粗粒度

    2. Spring security比较复杂难学 但是属于细粒度 权限控制更好

2.shiro的四大基石

身份验证、授权、密码学和会话管理

securityManager:核心对象 realm:获取数据接口

3.配置web.xml

主页:shiro的过滤器是很重要的,过滤请求达到限制权限的目的

<!--
    shiro的过滤器 所有请求都要过滤
    Delegating(委托)FilterProxy(代理)
    shiroFilter:这个名称非常重要
      -->
    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>targetFilterLifecycle</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

4.配置application-shiro.xml

在applicationContext.xml 里面引入applicationContext-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <!-- 真假过滤器(shiroFilter),安全管理器(securityManager),AiSellRealm(自定义realm),注解支持 -->
    <!--
            DefaultWebSecurityManager:创建Shiro的核心对象
            相当于: SecurityManager sm = new DefaultWebSecurityManager(myRealm);
    -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="jdbcRealm"/>
    </bean>


    <!-- 等会需要改成自己的Realm -->
    <bean id="jdbcRealm" class="cn.xiaji.web.shiro.AISellRealm">
        <!--密码的匹配器-->
        <property name="credentialsMatcher">
            <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
                <property name="hashAlgorithmName" value="MD5"/>
                <property name="hashIterations" value="1000"/>
            </bean>
        </property>
    </bean>

    <!--  这三个留着,你的权限就可以支持注解功能  -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          depends-on="lifecycleBeanPostProcessor"/>
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>


    <!--
        这个是真正的shiro过滤器
            要求:这个id的名称必需和web.xml中的那个过滤器名称一致
    -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <!-- 登录地址:如果你没有登录,就会去这个地方  -->
        <property name="loginUrl" value="/login"/>
        <!-- 登录成功会进入的页面 -->
        <property name="successUrl" value="/main.jsp"/>
        <!-- 没有权限进入的页面 -->
        <property name="unauthorizedUrl" value="/s/unauthorized.jsp"/>
        <!--
            路径 = anon -> 没有登录也可以访问这个路径
             /** = authc -> 所有路径都要权限拦截
        -->
        <!--<property name="filterChainDefinitions">
            <value>
                /s/login.jsp = anon
                /employee/index = perms[employee:index]
                /login =anon
                /** = authc
            </value>
        </property>-->
        <property name="filterChainDefinitionMap" ref="filterChainDefinitionMap"/>
    </bean>

    <!--实体工厂bean,把它返回值也变成一个bean-->
    <bean id="filterChainDefinitionMap" factory-bean="filterChainDefinitionMapFactory"
          factory-method="builderFilterChainDefinitionMap"/>
    <!-- 拿到生成map的工厂 -->
    <bean id="filterChainDefinitionMapFactory" class="cn.xiaji.web.shiro.FilterChainDefinitionMapFactory"/>

</beans>

5.配置FilterChainDefinitionMapFactory 放行需要放行的文件

注意:返回的Map必需是有序的(LinkedHashMap)

package cn.xiaji.web.shiro;
//encoding: utf-8

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author: xj
 * @contact: xiaruji520@gmail.com
 * @file: FilterChainDefinitionMapFactory.java
 */
/*

 */
public class FilterChainDefinitionMapFactory {
    public Map<String, String> builderFilterChainDefinitionMap() {
        Map<String, String> maps = new LinkedHashMap<>();
        //maps中加数据
        //设置放行
        maps.put("/s/*", "anon");
        maps.put("/login", "anon");
        maps.put("/easyui/**", "anon");
        maps.put("/js/**", "anon");
        maps.put("/json/**", "anon");
        maps.put("/css/**", "anon");
        maps.put("*.js", "anon");
        maps.put("*.css", "anon");
        maps.put("/images/**", "anon");
        //设置权限拦截
        maps.put("/employee/index", "perms[employee:index]");
        maps.put("/dept/index", "perms[dept:index]");
        //设置拦截所有
        maps.put("/**", "authc");
        return maps;
    }
}

6.自定义Realm

继承AuthorizingRealm,覆写下面两个方法

    //进行授权判断(权限)
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //1.拿到当前登录的用户
        String username = (String) principalCollection.getPrimaryPrincipal();
        //2.根据登录用户拿到角色与权限
        Set<String> roles = getRoles(username);
        Set<String> permissions = getPermissions(username);
        //3.创建返回的权限对象
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        //把角色放到权限对象中去
        authorizationInfo.setRoles(roles);
        authorizationInfo.setStringPermissions(permissions);
        return authorizationInfo;
    }

    //根据用户名拿到角色
    public Set<String> getRoles(String username) {
        Set<String> roles = new HashSet<String>();
        roles.add("admin");
        roles.add("root");
        return roles;
    }

    //根据用户名拿到权限
    public Set<String> getPermissions(String username) {
        Set<String> perms = new HashSet<String>();
        perms.add("employee:*");
        perms.add("dept:index");
        return perms;
    }

    //登录验证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //1.拿令牌(拿对应的用户名)
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        //2.根据用户名取拿密码
        String username = token.getUsername();
        Employee loginUser = employeeService.findByUsername(username);
        if (loginUser == null) {
            //返回null为:用户名错误
            return null;
        }
        //获取到盐值
        ByteSource salt = ByteSource.Util.bytes("xiaji");
        //getName():只是随便起的名
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username, loginUser.getPassword(), salt, getName());
        return authenticationInfo;
    }
上一篇:JAVA培训-Shiro安全框架


下一篇:页面反向映射之匿名页面