Shiro的简单使用

  1. Spring配置securityManager//程序里面就不用SecurityUtils.setSecurityManager(securityManager); // 注入SecurityManager
 <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="cacheManager" ref="cacheManager"/>
         <property name="realms" ref="jdbcRealm"/>
    </bean>
  1. 配置缓存CacheManager
 <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/> 
    </bean>  
    <bean id="authenticator"        class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
        <property name="authenticationStrategy">
            <bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean>
        </property>
    </bean>
  1. 配置 Realm 就是自定义的realm
  2. `








    这里的realm只需要实现AuthorizingRealm接口就行,因为里面包含两个需要重写的方法doGetAuthenticationInfo–进行登录授权,doGetAuthorizationInfo进行角色授权。
    4.配置 LifecycleBeanPostProcessor
<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>
5.启用 IOC 容器中使用 shiro 的注解. 但必须在配置了 LifecycleBeanPostProcessor 之后才可以使用




配置 ShiroFilter.

 <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <property name="loginUrl" value="/login.jsp"/>
        <property name="successUrl" value="/list.jsp"/>
        <property name="unauthorizedUrl" value="/unauthorized.jsp"/>
        <!--  
            配置哪些页面需要受保护. 
            以及访问这些页面需要的权限. 
            1). anon 可以被匿名访问
            2). authc 必须认证(即登录)后才可能访问的页面. 
            3). logout 登出.
            4). roles 角色过滤器
        -->
        <property name="filterChainDefinitions">
            <value>              
                /login.jsp = anon
                /shiro/login=anon
                /shiro/logout=logout  

                /user.jsp=roles[user]
                /admin.jsp=roles[admin]             
                # everything else requires authentication:
                /** = authc
            </value>
        </property>
    </bean>
  1. 配置ShiroFilter注意的点,因为filterChainDefinitions实质是保存的键值对,所以可以把数据保存在数据库。

realm的代码

package com.issimo.shiro.realms;

import java.util.HashSet;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

public class ShiroRealm extends AuthorizingRealm {

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("I am coming!"+token);
        //1.将AuthenticationToken 转换为UsernamePasswordToken
        UsernamePasswordToken uptoken=(UsernamePasswordToken) token;
        //2.从UsernamePasswordToken对象中取出username
        String username=uptoken.getUsername();
        //3.调用数据库方法,在数据库中查询username对应用户的记录
        System.out.println("从数据库获取username相关的用户信息"+username+"所对应的用户信息");
        //4.若用户不存在抛出UnKnownAccountException
        if("unknown".equals(username)){
            throw new UnknownAccountException("用户不存在");
        }
        //5.根据用户信息,决定是否抛出其他异常
        if("moster".equals(username)){
            throw new LockedAccountException("用户被锁定");
        }
        //根据用户的情况,来构建AuthenticationInfo对象 并返回!
        //以下信息是从数据库获取的
        //1).principal 认证的实体信息 可以说username 也可以是实体对象
        Object principal=username;
        //2).数据库中获取的密码
        Object credentials=null; //"fc1709d0a95a6be30bc5926fdb7f22f4";
        if("admin".equals(username)){
            credentials="038bdaf98f2037b31f1e75b5b4c9b26e";
        }else if("user".equals(username)){
            credentials="098d2c478e9c11555ce2823231e02ec1";
        }

        //3).realmName: 当前realm对象的Name,调用父类的getName()方法即可!
        String realmName=getName();
        //使用颜值加密
        ByteSource credentialsSalt=ByteSource.Util.bytes(username);
        SimpleAuthenticationInfo info=null;   //new SimpleAuthenticationInfo(principal, credentials, realmName);
        info=new SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName);
        return info;
    }



    //授权会被shiro回调的方法
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection Principals) {
        System.out.println("doGetAuthorizationInfo...");
        //从PrincipalCollection获取用户登录的信息
         Object principal=Principals.getPrimaryPrincipal();
        //利用用户登录的信息来获取当前用户的角色或者权限(肯恶搞需要查询数据库)
        Set<String> roles=new HashSet<>();
        roles.add("user");
        if("admin".equals(principal)){
            roles.add("admin");
        }
        //创建SimpleAuthorizationInfo 设置其roles属性
        SimpleAuthorizationInfo info =new SimpleAuthorizationInfo(roles);
        //返回SimpleAuthorizationInfo对象
        return info;
    }


}
  1. Handler代码
  2. `package com.issimo.shiro.handlers;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@RequestMapping(“/shiro”)
@Controller
public class ShiroHandler {

@RequestMapping("/login")
public String Login(@RequestParam("username") String username, @RequestParam("password") String password) {

Subject currentUser = SecurityUtils.getSubject();

    if (!currentUser.isAuthenticated()) {
        // 把用户名和密码封装为 UsernamePasswordToken 对象
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        // rememberme
        token.setRememberMe(true);
        try {
            System.out.println("1. " + token.hashCode());
            // 执行登录. 
            currentUser.login(token);
        } 
        // ... catch more exceptions here (maybe custom ones specific to your application?
        // 所有认证时异常的父类. 
        catch (AuthenticationException ae) {
            //unexpected condition?  error?
            System.out.println("登录失败: " + ae.getMessage());
        }
    }




    return "redirect:/list.jsp";

}

}

  1. 使用shiro三处可以连接数据库的地方:①filterChainDefinitions ②自定义的realms里的登录授权 ③ 自定义Realms里的角色授权
    总体来说 确实很难,因为 里面的英文单词 太长太多,而且有些单词仅仅只差1个字母 比如 AuthorizationInfo,AuthenticationInfo

`

`

猜你喜欢

转载自blog.csdn.net/qq_36664325/article/details/82181668