springboot集成shiro

记录一下简单学习shiro的过程,希望对小伙伴们有效。
所有整合代码已更新到码云,对上次sprinboot+layui的练习进行了优化,加入了shiro安全框架,链接:
码云链接
1.shiro外部结构
在这里插入图片描述
2.shiro内部结构
在这里插入图片描述
3.快速开始shiro
官网教程Apache Shiro | Simple. Java. Security.
github:GitHub - apache/shiro: Apache Shiro
3.1导入maven

<dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.4.1</version>
        </dependency>
        <!-- Shiro uses SLF4J for logging.  We'll use the 'simple' binding
             in this example app.  See http://www.slf4j.org for more info. -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.21</version>
           
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>1.7.21</version>
           
        </dependency>
        
        <!-- https://mvnrepository.com/artifact/log4j/log4j -->
		<dependency>
    		<groupId>log4j</groupId>
    		<artifactId>log4j</artifactId>
    		<version>1.2.17</version>
		</dependency>

3.2 log4j.properties

##apache日志
log4j.logger.org.apache=WARN

##spring日志
log4j.logger.org.springframework=WARN

##shiro日志
log4j.logger.org.apache.shiro=INFO
log4j.logger.org.apache.shiro.util.ThreadContext=WARN
log4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN

3.3 shiro.ini

# =============================================================================
# Tutorial INI configuration
#
# Usernames/passwords are based on the classic Mel Brooks' film "Spaceballs" :)
# =============================================================================

# -----------------------------------------------------------------------------
# Users and their (optional) assigned roles
# username = password, role1, role2, ..., roleN
# -----------------------------------------------------------------------------
[users]
root = secret, admin
guest = guest, guest
presidentskroob = 12345, president
darkhelmet = ludicrousspeed, darklord, schwartz
lonestarr = vespa, goodguy, schwartz

# -----------------------------------------------------------------------------
# Roles with assigned permissions
# roleName = perm1, perm2, ..., permN
# -----------------------------------------------------------------------------
[roles]
admin = *
schwartz = lightsaber:*
goodguy = winnebago:drive:eagle5

3.4官方案例分析(Quickstart)

@SuppressWarnings("deprecation")
public class Quickstart {

    private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);


    public static void main(String[] args) {

        
        //固定代码,获取配置文件信息,利用工厂模式创建对象(与mybatis一样)
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        SecurityManager securityManager = factory.getInstance();
        //设置单例模式
        SecurityUtils.setSecurityManager(securityManager);
        
        

        // 用户subject
        // 重点:获取当前用户
        Subject currentUser = SecurityUtils.getSubject();
        // 重点:获取当前用户session,存取值
        Session session = currentUser.getSession();
        session.setAttribute("someKey", "aValue");
        String value = (String) session.getAttribute("someKey");
        if (value.equals("aValue")) {
            log.info("Retrieved the correct value! [" + value + "]");
        }

        // 判断当前用户是否被验证
        if (!currentUser.isAuthenticated()) {
            //Token:令牌,没有获取,随机
            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
            token.setRememberMe(true);//记住我
            
            try {
                currentUser.login(token);//执行了登录
            } catch (UnknownAccountException uae) {
                log.info("There is no user with username of " + token.getPrincipal());
            } catch (IncorrectCredentialsException ice) {
                log.info("Password for account " + token.getPrincipal() + " was incorrect!");
            } catch (LockedAccountException lae) {
                log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                        "Please contact your administrator to unlock it.");
            }
            // ... catch more exceptions here (maybe custom ones specific to your application?
            catch (AuthenticationException ae) {
                //unexpected condition?  error?
            }
        }

        //say who they are:
        //print their identifying principal (in this case, a username):
        log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");

        //test a role:权限判断
        if (currentUser.hasRole("schwartz")) {
            log.info("May the Schwartz be with you!");
        } else {
            log.info("Hello, mere mortal.");
        }

        //粗粒度
        //test a typed permission (not instance-level)
        if (currentUser.isPermitted("lightsaber:wield")) {
            log.info("You may use a lightsaber ring.  Use it wisely.");
        } else {
            log.info("Sorry, lightsaber rings are for schwartz masters only.");
        }
        //细粒度
        //a (very powerful) Instance Level permission:
        if (currentUser.isPermitted("winnebago:drive:eagle5")) {
            log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
                    "Here are the keys - have fun!");
        } else {
            log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
        }

        //all done - log out!注销
        currentUser.logout();

        System.exit(0);
    }
}

3.5 重要代码总结

// 重点:获取当前用户
Subject subject = SecurityUtils.getSubject();
subject.getPrincipal()
// 重点:获取当前用户shiro中的session(不是http里面session),存取值
Session session = currentUser.getSession();
//判断当前用户是否被验证
currentUser.isAuthenticated()
//权限判断
currentUser.hasRole()

4.springboot集成shiro
4.1导入坐标

<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>1.8.0</version>
		</dependency>
  <!-- thymeleaf-整合-shiro -->
		<!-- https://mvnrepository.com/artifact/com.github.theborakompanioni/thymeleaf-extras-shiro -->
		<dependency>
    		<groupId>com.github.theborakompanioni</groupId>
    		<artifactId>thymeleaf-extras-shiro</artifactId>
    		<version>2.1.0</version>
		</dependency>

4.2针对shiro三个重要类,编写配置类

@Configuration
public class ShiroConfig
{
    
    @Autowired
    DefaultWebSessionManager defaultSessionManager;
    
    /*
     * 固定代码(对应三个主要对象) Suject:用户    SecurityManager:管理所有用户    Realm:连接数据
     */
    //ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
        
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
                
        //关联DefaultWebSecurityManager,设置安全管理器
        bean.setSecurityManager(defaultWebSecurityManager);
        
        
        //添加shiro的内置过滤器
        /*
         * anon: 无需认证就可以访问
         * authc: 必须认证才能访问
         * user: 必须拥有 记住我 功能才能用
         * perms: 拥有对某个资源的权限才能访问
         * role: 拥有某个角色权限才能访问
         * 
         */
        //创建条件集合
        Map<String, String> filterMap = new LinkedHashMap<>();
        
        
        //授权:必须是user且拥有add权限
        filterMap.put("/role/role-list", "perms[role:list]");
        
        //授权:必须是user且拥有update权限
        filterMap.put("/admin/admin-list", "perms[admin:list]");
        
        //添加条件
//        filterMap.put("/user/add", "authc");
//        filterMap.put("/user/update", "authc");
        filterMap.put("/role/*", "authc");
        filterMap.put("/admin/*", "authc");
        //设置登入请求
        bean.setLoginUrl("/");
        
        //设置未授权请求
        bean.setUnauthorizedUrl("/noauth");
        
        
        //添加条件集合
        bean.setFilterChainDefinitionMap(filterMap);
        return bean;
    }
    
   //DefaultWebSecurityManager @Qualifier("userRealm")绑定下面的userRealm()
    @Bean(name="securityManager")
    public DefaultWebSecurityManager getDafaultWebSecurityManage(@Qualifier("userRealm") UserRealm userRealm) {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        //关联UserRealm
        defaultWebSecurityManager.setRealm(userRealm);
      //设置DefaultWebSecurityManager的SessionManager,解决jsessionid问题
        defaultWebSecurityManager.setSessionManager(defaultSessionManager);
        
        return defaultWebSecurityManager;
    }
    
    //创建realm对象,需要自定义类
    @Bean(name="userRealm")
    public UserRealm userRealm() {
        return new UserRealm();
    }
    
  //创建DefaultWebSessionManager类,并DI注入到IOC容器中,解决jsessionid问题
    @Bean
    public DefaultWebSessionManager mySessionManager(){
        DefaultWebSessionManager defaultSessionManager = new DefaultWebSessionManager();
        //将sessionIdUrlRewritingEnabled属性设置成false
        defaultSessionManager.setSessionIdUrlRewritingEnabled(false);
        return defaultSessionManager;
    }
    
    //注册ShiroDialect:thymeleaf-整合-shiro
    @Bean
    public ShiroDialect getShiroDialect() {
        return new ShiroDialect();
    }


}
public class UserRealm extends AuthorizingRealm
{
    
    @Autowired
    AcgUserServiceImpl acgUserService;
    
    @Autowired
    AcgRoleServiceImpl acgRoleService;
    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("执行了:授权doGetAuthenticationInfo");
        
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //授权
        //info.addStringPermission("user:add");
        
        //从认证拿到当前用户
       Subject subject=SecurityUtils.getSubject();
       AcgUser currentUser = (AcgUser)subject.getPrincipal();
       
        //授权
       AcgRole acgRole = acgRoleService.getAcgRoleById(currentUser.getRole_id());
       String[] roleList = acgRole.getRole_hasrole().split(";");
       for(int i=0;i<roleList.length;i++) {
           info.addStringPermission(roleList[i]);
       }
       
        return info;
    }
    
    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("执行了:认证doGetAuthenticationInfo");
        
        //这里的token就是前端传值封装的token,token是全局的
        UsernamePasswordToken userToken=(UsernamePasswordToken) token;
        
        //用户名 密码 ,数据库中取
        AcgUser user = acgUserService.getAcgUserByUsername(userToken.getUsername());
              
        
        if(user==null) {
            return null;//抛出异常,UnknownAccountException
        }
        
        
        //密码认证,shiro做,避免密码泄露(这里密码默认加密了,也可以更换加密算法),第一个参数:传递对象授权,第二个参数:验证密码
        return new SimpleAuthenticationInfo(user,user.getUser_password(),"");
    }

}

4.3登录判断,注销判断,未授权

    public String login(@RequestParam("username") String username, @RequestParam("pass") String pass, Model model,
            HttpSession session) {
      //shiro获取当前用户
        Subject subject = SecurityUtils.getSubject();
        //token封装用户登录数据
        UsernamePasswordToken token = new UsernamePasswordToken(username,pass);
        //执行登录:没有异常就登录成功
        try {
            subject.login(token);
            session.setAttribute("username", username);
            return "firstpage";
        }
        catch (UnknownAccountException e) {
            model.addAttribute("msg", "用户名不存在!");
            return "index";
        }
        catch (IncorrectCredentialsException e) {
            model.addAttribute("msg", "密码错误!");
            return "index";
        }

    }
      @RequestMapping("/outlogin")
    public String outLogin(HttpSession session) {
        if (session != null) {
            session.removeAttribute("username");
        }
        //单例模式
        Subject currentUser = SecurityUtils.getSubject();
        //all done - log out!注销
        //关闭shiro
        currentUser.logout();
        return "index";
    }
     //跳转未授权页面
    @RequestMapping("/noauth")
    @ResponseBody
    public String Noauth() {
        return "页面未授权!";
        
    }

4.4前端页面
引入

<html  xmlns:th="http://www.thymeleaf.org"
       xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro">

判断
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值