SpringBoot整合shiro

1.shiro是什么?

Shiro是Apache下的一个开源项目。shiro属于轻量级框架,相对于SpringSecurity简单的多,也没有SpringSecurity那么复杂。以下是我自己学习之后的记录。

官方架构图如下:

 

官方架构图

2.主要功能

shiro主要有三大功能模块:

1. Subject:主体,一般指用户。

2. SecurityManager:安全管理器,管理所有Subject,可以配合内部安全组件。(类似于SpringMVC中的DispatcherServlet)

3. Realms:用于进行权限信息的验证,一般需要自己实现。

3.细分功能

1. Authentication:身份认证/登录(账号密码验证)。

2. Authorization:授权,即角色或者权限验证。

3. Session Manager:会话管理,用户登录后的session相关管理。

4. Cryptography:加密,密码加密等。

5. Web Support:Web支持,集成Web环境。

6. Caching:缓存,用户信息、角色、权限等缓存到如redis等缓存中。

7. Concurrency:多线程并发验证,在一个线程中开启另一个线程,可以把权限自动传播过去。

8. Testing:测试支持;

9. Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问。

10. Remember Me:记住我,登录后,下次再来的话不用登录了。

4、上程序

目录结构

pom.xml

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
        </dependency>

        <!--springboot中的thymeleaf依赖-->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-java8time</artifactId>
        </dependency>

        <!--Shiro与thymeleaf整合-->
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.1.0</version>
        </dependency>


        <!--Shiro 与 springboot整合包-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.1</version>
        </dependency>

        <!-- MYSQL驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!--Mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>

        <!--log4j-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <!--druid-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.12</version>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>

    </dependencies>

 UserRealm.java

package com.csp.config;
import com.csp.mapper.UserMapper;
import com.csp.pojo.User;
import com.csp.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

public class UserRealm extends AuthorizingRealm {

    @Autowired
    UserMapper userMapper;

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //info.addStringPermission("user:add");

        //获取当前用户对象
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();

        info.addStringPermission(user.getPerms());

        return info;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        User user =  userMapper.queryUserByName(userToken.getUsername());

        if( user==null )
            return null;

//密码认证
        return new SimpleAuthenticationInfo(user, user.getUserpwd(),"");
    }
}

ShiroConfig.java

package com.csp.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    //3 ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //设置安全管理器
        bean.setSecurityManager(securityManager);
        //添加过滤器
        /** 添加过滤器
         * anon 无需认证就可访问
         * authc  必须认证才能访问
         * user   必须拥有“记住我”功能才能使用(较少使用)
         * perms: 拥有对某个资源的权限才能访问
         * role:  拥有某个角色权限才能访问
         */
        Map<String, String> filterMap = new LinkedHashMap<>();

        //设置拦截
        filterMap.put("/user/add", "perms[user:add]");
        filterMap.put("/user/*", "authc");

        bean.setFilterChainDefinitionMap(filterMap);
        //设置登录页
        bean.setLoginUrl("/login");
        //未授权跳转页面
        bean.setUnauthorizedUrl("/unauth");

        return bean;
    }

    //2 DefaultWebSecurityManager
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    //1 创建Realm对象
    @Bean
    public UserRealm userRealm(){
        return new UserRealm();
    }

    //Shiro 与 thymeleaf 整合
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }
}

MyController.java

package com.csp.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MyController {

    @RequestMapping("/")
    public String toIndex(Model model){
        model.addAttribute("msg","Hello,Shiro!!!");
        return "index";
    }

    @RequestMapping("/login")
    public String toLogin(){
        return "/user/login";
    }

    @RequestMapping("/logout")
    public String logout(){
        Subject user = SecurityUtils.getSubject();
        user.logout();
        return "index";
    }

    @RequestMapping("/toAuthc")
    public String toAuthc( String username, String userpwd, Model model){

        //获取当前用户对象
        Subject user = SecurityUtils.getSubject();
        //封装用户登录数据
        UsernamePasswordToken token=new UsernamePasswordToken(username,userpwd);

        try {
            user.login(token);

            //设置登录状态
            Session session = user.getSession();
            session.setAttribute("loginuser", true);

            return "index";
        }catch (UnknownAccountException e){
            //用户名不存在
            model.addAttribute("msg","用户名不存在!");
            return "/user/login";
        }catch (IncorrectCredentialsException e){
            //密码错误
            model.addAttribute("msg","密码错误!");
            return "/user/login";
        }
    }

    @RequestMapping("/user/add")
    public String userAdd(){
        return "/user/add";
    }

    @RequestMapping("/unauth")
    @ResponseBody
    public String unAuthorized(){
        return "未经授权,无法访问此页面";
    }
}

 

posted @ 2022-01-05 08:55  spring8889  阅读(357)  评论(0)    收藏  举报