shiro历程

1,首先想学shiro

2,其次想在springboot上学习shiro

3,我又不会springboot,看视频教程了解了下

4,开始配置,也可以说是改造,改造一个视频教程的代码

5,shiro配置全局拦截器shiroFilter,拦截所有请求(感觉这个可有可无,有大佬可以解释下吗,那种web.xml的方式,说是必须配置)

/**
 * 注册DelegatingFilterProxyShiro
 * @param dispatcherServlet
 * @return
 */
@Bean
public FilterRegistrationBean filterRegistrationBean() {
    FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
    filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));
    //  该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理
    filterRegistration.addInitParameter("targetFilterLifecycle", "true");
    filterRegistration.setEnabled(true);
    filterRegistration.addUrlPatterns("/*");
    return filterRegistration;
}

6,配置进行授权和认证的 Realm 

    @Bean
    public MyRealm myRealm(){
        MyRealm myRealm = new MyRealm();
        myRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return  myRealm;
    }

    MyRealm类实现,setCredentialMatcher方法为实现加密方式。

    

package com.atguigu.shiro.realm;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
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 MyRealm extends AuthorizingRealm {

   /**
    * 授权方法:
    * 1. 实际返回的是 SimpleAuthorizationInfo 类的实例
    * 2. 可以调用 SimpleAuthorizationInfo addRole 来添加当前登录 user 的权限信息. 
    * 3. 可以调用 PrincipalCollection 参数的 getPrimaryPrincipal() 方法来获取用户信息 
    */
   @Override
   protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
      SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
      
      Object principal = principalCollection.getPrimaryPrincipal();
      
      if("admin".equals(principal)){
         info.addRole("admin");
      }
      if("user".equals(principal)){
         info.addRole("list");
      }
      
      info.addRole("user");
      
      return info;
   }

   /**
    * 认证方法
    * 1. 编写表单: 表单的 action、和 usernamepassword 的参数都是什么 ? 
    * 回答: 提交到你想提交的地方, username password 也参数名称都任意. 
    * 2. 例如, 提交到了一个 SpringMVC handler: 
    * 1). 获取用户名、密码
    * 2). 
    * Subject currentUser = SecurityUtils.getSubject();
    * UsernamePasswordToken token = new UsernamePasswordToken(username, password);
    * currentUser.login(token);
    * 3. Subject 调用 login 方法时, 即会触发当前的 doGetAuthenticationInfo 方法. 且把 
    * UsernamePasswordToken 对象传入, 然后再该方法中执行真正的认证: 访问数据库进行比对. 
    * 1). 获取用户名和密码
    * 2). 
    */
   @Override
   protected AuthenticationInfo doGetAuthenticationInfo(
         AuthenticationToken token) throws AuthenticationException {
      System.out.println(token.getPrincipal());
      System.out.println(token.getCredentials());
      
      //1.  token 中获取登录的 username! 注意不需要获取 password.
      
      //2. 利用 username 查询数据库得到用户的信息. 
      
      //3. 创建 SimpleAuthenticationInfo 对象并返回. 注意该对象的凭证式从数据库中查询得到的. 
      //而不是页面输入的. 实际的密码校验可以交由 Shiro 来完成
      
      //4. 关于密码加密的事: shiro 的密码加密可以非常非常的复杂, 但实现起来却可以非常简单.
      //1). 可以选择加密方式: 在当前的 realm 中编写一个 public 类型的不带参数的方法, 使用 @PostConstruct
      //注解进行修饰, 在其中来设置密码的匹配方式.
      //2). 设置盐值: 盐值一般是从数据库中查询得到的.  
      //3). 调用 new SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName)
      //构造器返回 SimpleAuthenticationInfo 对象:  credentialsSalt       //ByteSource credentialsSalt = new Md5Hash(source);
      
      //登陆的主要信息: 可以是一个实体类的对象, 但该实体类的对象一定是根据 token  username 查询得到的. 
      Object principal = token.getPrincipal();
      //认证信息: 从数据库中查询出来的信息. 密码的比对交给 shiro 去进行比较
      String credentials = "afdbaa3ee63a8b4e97196dcfd24b03fc";
      //设置盐值: 
      String source = "abcdefg";
      ByteSource credentialsSalt = new Md5Hash(source);
      System.out.println(credentialsSalt); 
      
      //当前 Realm  name
      String realmName = getName();
      SimpleAuthenticationInfo info = 
            new SimpleAuthenticationInfo(principal, credentials, 
                  credentialsSalt, realmName);
      
      return info;
   }

   //@PostConstruct: 相当于 bean 节点的 init-method 配置. 
   public void setCredentialMatcher(){
      HashedCredentialsMatcher  credentialsMatcher = new HashedCredentialsMatcher();
      
      credentialsMatcher.setHashAlgorithmName("MD5");
      credentialsMatcher.setHashIterations(1024);
      
      setCredentialsMatcher(credentialsMatcher);
   }
   
   public static void main(String[] args) {
      String saltSource = "abcdefg";
      
      String hashAlgorithmName = "MD5";
      String credentials = "admin";
      Object salt = new Md5Hash(saltSource);
      int hashIterations = 1024;
            
      Object result = new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations);
      System.out.println(result);
      System.out.println("68f3139a38b232392cc9d3b6ddd762f7".equals(result.toString()));
   }

}

7,配置securityManager,目前解释不清楚什么用处,将myRealm放进去

  @Bean
    public DefaultWebSecurityManager securityManager(){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myRealm());
        return securityManager;
    }
 

8,<!-- 配置 Bean 后置处理器: 会自动的调用和 Spring 整合后各个组件的生命周期方法. -->  @Bean    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){        LifecycleBeanPostProcessor lifecycleBeanPostProcessor = new LifecycleBeanPostProcessor();        return  lifecycleBeanPostProcessor;    }

9,<!-- 使 Shiro 的注解起作用, Shiro 的注解标示在方法上. 例如 @RequiresRoles、@RequiresPermissions --> <!-- 因为目前是在 Handler 的方法上添加注解, 所以以下的配置需要作用在 SpringMVC 的 IOC 容器中. 而不是其父容器中.  -->    @Bean    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());        return  authorizationAttributeSourceAdvisor;

    }

10, <!-- 配置 ShiroFilter bean: 该 bean 的 id 必须和 web.xml 文件中配置的 shiro filter 的 name 一致  -->

    

@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilterFactoryBean(){

    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    shiroFilterFactoryBean.setSecurityManager(securityManager());
    shiroFilterFactoryBean.setSuccessUrl("/shiro-success");
    shiroFilterFactoryBean.setLoginUrl("/login");
    shiroFilterFactoryBean.setUnauthorizedUrl("/shiro-unauthorized");
    Map<String ,String> filterChainMap = new LinkedHashMap<>();
    filterChainMap.put("/shiro-logout","logout");
    filterChainMap.put("/login ","anon");
    filterChainMap.put("/shiro-* ","anon");
    filterChainMap.put("/**","authc");
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);
    return shiroFilterFactoryBean;
}


11,controller实现,jsp就不展示了,只有一个表单,

     @RequestMapping("/shiro-login")
    public String toLogin(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse){
        String username = httpServletRequest.getParameter("username");
        String password = httpServletRequest.getParameter("password");
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try {
            //执行认证操作.
            subject.login(token);
        }catch (AuthenticationException ae) {
            System.out.println("登陆失败: " + ae.getMessage());
            return "/shiro-login";
        }
        return "shirl-success";
    }
    @RequestMapping("/login")
    public String toLoginJsp(HttpServletRequest httpServletRequest){
        return "shiro-login";

    }

12,subject.login(token); 调用之后,直接进入myRealm的doGetAuthenticationInfo()方法,可以在那个方法实现密码对比

13,doGetAuthorizationInfo()方法为权限的控制,还不明白,日后补上


14,目录结构


15,注解简单应用

@RequiresRoles("list")
@RequestMapping("/list")
public String list(){
    System.out.println("...list...");
    return "list";
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值