智销系统day05-Spring集成shiro

1.自定义Realm

①创建一个Realm类

  • 自定义Realm继承AuthorizingRealm类
  • 重写授权和登录验证方法

②重写登录验证方法

  • 该方法返回null,表示用户名错误
  • 只需将密码交给shiro,shiro可以自动帮你判断密码是否正确
  • 需要两个密码,一个传过来的,一个数据库中查询的
  • 用户名和密码验证后,需要创建SimpleAuthenticationInfo对象返回
    创建SimpleAuthenticationInfo:
    • 第一个参数:principal(主体) =》登录成功后在任何地方都可以拿到的对象
    • 以前开始登录成功我们就把用户放到session中
    • 第二个参数:密码(从数据库查出来的密码)
    • 第三个参数:盐值salt
    • 第四个参数:当前realm的名称(随便取)
//判断密码是否正确
//shiro做准备了一个工具直接让我们把数据变成 ByteSource格式
ByteSource salt = ByteSource.Util.bytes("itsource");
AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username,password,salt,getRealmName());

③授权方法重写

  • 创建授权对象
  • 获取角色并设置角色
  • 获取权限并设置权限
/*
* 授权(之后的权限数据获取都在这里面)
* */
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    //创建授权对象
    SimpleAuthorizationInfo authorizationInfo= new SimpleAuthorizationInfo();
    //获取角色并设置角色
    Set<String> roles = findRoles();
    authorizationInfo.setRoles(roles);
    //获取权限并设置权限
    Set<String> permissions = findPermissions();
    authorizationInfo.setStringPermissions(permissions);
    return authorizationInfo;
}

自定义Realm完整代码

public class MyRealm extends AuthorizingRealm {
    /*
    * 授权(之后的权限数据获取都在这里面)
    * */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //创建授权对象
        SimpleAuthorizationInfo authorizationInfo= new SimpleAuthorizationInfo();
        //获取角色并设置角色
        Set<String> roles = findRoles();
        authorizationInfo.setRoles(roles);
        //获取权限并设置权限
        Set<String> permissions = findPermissions();
        authorizationInfo.setStringPermissions(permissions);
        return authorizationInfo;
    }

    /*
    * 现在是模拟拿到对应的角色信息(以后我们会根据真实的登录用户去查找对应的角色)
    * */
    private Set<String> findRoles(){
        Set<String> roles = new HashSet<String>();
        roles.add("it");
        return roles;
    }

    private Set<String> findPermissions(){
        Set<String> permissions = new HashSet<String>();
        permissions.add("employee:save");
        return permissions;
    }

    /*
    * 登录
    * 1.该方法返回null,表示用户名错误
    * 2.只需将密码交给shiro,shiro可以自动帮你判断密码是否正确(需要两个密码,一个传过来的,一个数据库中查询到的)
    * */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //拿到用户名密码令牌(强转)
        UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
        //获取用户名(传过来的)
        String username = token.getUsername();
        //判断用户名是否正确(查询出来的密码)
        String password = findByUsername(username);
        //返回的密码为null,表示用户名不存在
        if (password == null){
            return null;
        }
        //判断密码是否正确
        /**
         * 第一个参数:principal(主体) =》 登录成功后在任何地方都可以拿到的对象
         *      以前开始登录成功我们就把用户放到session中
         * 第二个参数:密码(从数据库查出来的密码)
         * 第三个参数:盐值salt
         * 第四个参数:当前realm的名称(随便取)
         */
        //shiro做准备了一个工具直接让我们把数据变成 ByteSource格式
        ByteSource salt = ByteSource.Util.bytes("itsource");
        AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username,password,salt,getRealmName());
        return authenticationInfo;
    }

    private String getRealmName(){
        return "myRealm";
    }
    /*
    * 模拟获取密码的方法
    * */
    private String findByUsername(String username){
        if("admin".equals(username)){
            return "831d092d59f6e305ebcfa77e05135eac";
        }else if("gg".equals(username)){
            return "123";
        }
        return null;
    }
}

2.密码加密

  • 加密要使用加密算法(散列,哈希)
  • 我们主要使用MD5,SHA
  • 创建加密对象是传递的参数:
    SimpleHash hash = new SimpleHash(“MD5”,“123456”,“itsource”,10);
    • algorithmName:加密算法名称
    • source:密码源
    • salt:盐值
    • hasIterations:迭代次数

①凭证匹配器(HashedCredentialsMatcher)

通过凭证匹配器,设置加密方式和迭代次数
自定义realm类中

//创建一个凭证匹配器
HashedCredentialsMatcher matcher= new HashedCredentialsMatcher();
//设置加密算法名称
matcher.setHashAlgorithmName("MD5");
//设置迭代次数
matcher.setHashIterations(10);
//设置凭证匹配器(密码验证规则) Credentials(凭证) Matcher(匹配器)
myRealm.setCredentialsMatcher(matcher);

-设置加盐(salt),需要在登录验证方法创建SimpleAuthenticationInfo对象时设置
ByteSource salt = ByteSource.Util.bytes(“itsource”);

//shiro做准备了一个工具直接让我们把数据变成 ByteSource格式
ByteSource salt = ByteSource.Util.bytes("itsource");
AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username,password,salt,getRealmName());

测试加密:

/**
 *  123456 MD5 =》 e10adc3949ba59abbe56e057f20f883e
 *  123456 MD5 10次 =》 4a95737b032e98a50c056c41f2fa9ec6
 *  123456 MD5 10次 itsource=》 831d092d59f6e305ebcfa77e05135eac
 */
@Test
public void test() throws Exception{
    /*
    * algorithmName:加密算法名称
    * source:密码源
    * salt:盐值
    * hasIterations:迭代次数
    * */
    SimpleHash hash = new SimpleHash("MD5","123456","itsource",10);
    System.out.println(hash.toHex());
}

3.测试自定义realm和密码加密

测试代码:

public class MyRealmTest {
    @Test
    public void testMyRealm() throws Exception{
        //获取权限管理对象
        DefaultSecurityManager securityManager= new DefaultSecurityManager();
        //获取一个(自定义)realm对象
        MyRealm myRealm = new MyRealm();

        //创建一个凭证匹配器
        HashedCredentialsMatcher matcher= new HashedCredentialsMatcher();
        //设置加密算法名称
        matcher.setHashAlgorithmName("MD5");
        //设置迭代次数
        matcher.setHashIterations(10);
        //设置凭证匹配器(密码验证规则) Credentials(凭证) Matcher(匹配器)
        myRealm.setCredentialsMatcher(matcher);

        //将realm放入权限管理对象中
        securityManager.setRealm(myRealm);
        //将权限管理器放入工具
        SecurityUtils.setSecurityManager(securityManager);
        //获取当前用户
        Subject subject = SecurityUtils.getSubject();

        //判断用户是否登录
        System.out.println("判断用户是否登录"+subject.isAuthenticated());
        if(!subject.isAuthenticated()){
            try {
                //创建一个用户名密码令牌
                UsernamePasswordToken token = new UsernamePasswordToken("admin","123456");
                //通过令牌,登录当前用户
                subject.login(token);
                //再次判断用户是否登录
                System.out.println("再次判断用户是否登录"+subject.isAuthenticated());
            } catch (UnknownAccountException e) {
                //UnknownAccountException(不知道用户异常)
                System.out.println("用户名错误!!!");
                e.printStackTrace();
            }catch (IncorrectCredentialsException e){
                //IncorrectCredentialsException(不正确凭证(密码错误)异常)
                System.out.println("密码错误!!!");
                e.printStackTrace();
            }catch (AuthenticationException e){
                System.out.println("sorry!!!");
                e.printStackTrace();
            }
        }
        //判断该用户是否有某一个角色
        System.out.println(subject.hasRole("admin"));
        //判断是否有某个权限
        System.out.println("判断用户是否有employee:save权限"+subject.isPermitted("employee:save"));
        System.out.println("判断用户是否有employee:update权限"+subject.isPermitted("employee:update"));
        System.out.println("判断用户是否有employee:delete权限"+subject.isPermitted("employee:delete"));
        System.out.println("判断用户是否有department:save权限"+subject.isPermitted("department:save"));

    }
}

4.Spring集成shiro

①导包

  • 导入shiro核心包
<!-- shiro(权限框架)的支持包 -->
<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-all</artifactId>
  <version>1.4.0</version>
  <type>pom</type>
</dependency>
<!-- shiro与Spring的集成包 -->
<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-spring</artifactId>
  <version>1.4.0</version>
</dependency>

②web.xml配置代理过滤器

  • 该过滤器除了拦截,啥也不做
<!--
    shiro过滤器(除了拦截,啥也不做)
        Delegating: 授(权); 把(工作、权力等)委托(给下级); 选派(某人做某事);
        Proxy:代理
  -->
  <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>

③创建并配置applicationContext-shiro.xml

注意applicationContext.xml需要引入applicationContext-shiro.xml
applicationContext.xml代码

<!--引入applicationContext-shiro.xml文件-->
<import resource="classpath:applicationContext-shiro.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">


    <!--
        创建权限管理器对象
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(aisellRealm);
    -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="aisellRealm"/>
    </bean>

    <!--
        创建realm(获取权限数据的对象)
    -->
    <bean id="aisellRealm" class="com.luo.aisell.web.shiro.AisellRealm">
        <property name="name" value="aisellRealm"/>
        <!--
            创建 凭证credentials匹配器Matcher
            aisellRealm.setCredentialsMatcher(matcher);
        -->
        <property name="credentialsMatcher">
            <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
                <!--加密算法-->
                <property name="hashAlgorithmName" value="MD5"/>
                <!--迭代次数-->
                <property name="hashIterations" value="10"/>
            </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必须和shiro过滤器的名称相同-->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- 引入了权限管理器 -->
        <property name="securityManager" ref="securityManager"/>
        <!-- 如果没有登录成功,就会进入这个页面 -->
        <property name="loginUrl" value="/s/login.jsp"/>
        <!--登录成功后,会进入的页面-->
        <property name="successUrl" value="/s/success.jsp"/>
        <!--如果没有权限,你会进入这个页面-->
        <property name="unauthorizedUrl" value="/s/unauthorized.jsp"/>
        <!--
            filterChainDefinitions:过滤器描述(注意描述是有顺序的)
            anon:不登录也可以访问的(游客也可以访问)
            /s/permission.jsp = perms[employee:index]
            只有employee:index权限,才能访问/s/permission.jsp
            authc:必须登录才可以访问的
        -->
        <property name="filterChainDefinitions">
            <value>
                /login = anon
                /s/permission.jsp = perms[employee:index]
                /** = authc
            </value>
        </property>
    </bean>
</beans>

④准备工厂返回权限信息

  • 返回的Map值是有顺序的
  • 修改后要重启(热启动无效)

这个类就是咱们获取权限Map的工厂

//这个类就是咱们获取权限Map的工厂
public class FilterChainDefinitionMapFactory {
    /**
     * 这个方法就会返回咱们的权限数据(它是有顺序)
     */
    public Map<String,String> creatMap(){
        //注意:这里的map是有顺序的
        Map<String,String> map = new LinkedHashMap<>();
        map.put("/login","anon");
        map.put("/s/permission.jsp","perms[employee:save]");
        map.put("/**","authc");
        return map;
    }
}

applicationContext-shiro.xml代码

<!-- shiro真正的权限过滤器 注意:这个id必须和shiro过滤器的名称相同-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <!-- 引入了权限管理器 -->
    <property name="securityManager" ref="securityManager"/>
    <!-- 如果没有登录成功,就会进入这个页面 -->
    <property name="loginUrl" value="/s/login.jsp"/>
    <!--登录成功后,会进入的页面-->
    <property name="successUrl" value="/s/success.jsp"/>
    <!--如果没有权限,你会进入这个页面-->
    <property name="unauthorizedUrl" value="/s/unauthorized.jsp"/>
    <!--
        filterChainDefinitions:过滤器描述(注意描述是有顺序的)
        anon:不登录也可以访问的(游客也可以访问)
        authc:必须登录才可以访问的
    -->
    <!--引用map-->
    <property name="filterChainDefinitionMap" ref="filterChainDefinitionMap"/>
</bean>
<!--通过工厂方法获得获得一个map对象  将它变成一个bean-->
<bean id="filterChainDefinitionMap" factory-bean="filterChainDefinitionMapFactory" factory-method="creatMap"/>
<!--创建map工厂-->
<bean id="filterChainDefinitionMapFactory" class="com.luo.aisell.web.shiro.FilterChainDefinitionMapFactory"/>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值