SpringBoot集成ShiRo

1、首先加上maven依赖的jar包

    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-core</artifactId>
      <version>1.4.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-spring</artifactId>
      <version>1.4.0</version>
    </dependency>

 

在以前spring集成shiro的时候,会在web.xml和spring.xml中配置很多文件,在springboot中没有xml文件,所以通过@bean的方式来配置

 

2.编写一个配置类


package cn.et.demo03.config;

import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;

import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;


@Configuration
public class ShiRoConfig {
    /**
     等价于 web.xml配置
     <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>
     * @return
     */
    @Bean
    public FilterRegistrationBean webShiRoFilter(){
        FilterRegistrationBean frb=new FilterRegistrationBean();
        DelegatingFilterProxy dfp=new DelegatingFilterProxy();
        frb.setFilter(dfp);
        frb.setName("shiRoFilter");
        LinkedHashSet<String> linkedHashSet = new LinkedHashSet<String>();
        linkedHashSet.add("/*");
        frb.setUrlPatterns(linkedHashSet);


        Map<String, String> initParameters=new HashMap<String, String>();
        initParameters.put("targetFilterLifecycle", "true");
        frb.setInitParameters(initParameters);
        return frb;
    }
    /**
     * 配置我的realm
     * @return
     */
    @Bean
    public Realm myRealm(){
        return new MyRealm();
    }

    /**
     * 定义默认的securityManager
     * @return
     */
    @Bean
    public DefaultWebSecurityManager securityManager(@Autowired Realm myRealm){
        DefaultWebSecurityManager dwm=new DefaultWebSecurityManager();
        dwm.setRealm(myRealm);
        return dwm;
    }

    /**
     * 定义和过滤器一致名字的shiRoFilterFactoryBean
     */
    @Bean
    public ShiroFilterFactoryBean shiRoFilter(@Autowired SecurityManager securityManager){
        ShiroFilterFactoryBean filterFactoryBean=new ShiroFilterFactoryBean();
        filterFactoryBean.setSecurityManager(securityManager);
//      如果需要授权就跳转到这个路径
        filterFactoryBean.setLoginUrl("/Login.jsp");
//      如果没有权限就跳转到这个路径
        filterFactoryBean.setUnauthorizedUrl("/RoleError.jsp");

//      自定义一个过滤器
        Map<String, String> urls=new HashMap<String, String>();
        urls.put("/**", "myFilter");
//        urls.put("/Login.jsp", "anon");
//        urls.put("/LoginSuccess.jsp", "authc");
        filterFactoryBean.setFilterChainDefinitionMap(urls);
        return filterFactoryBean;
    }
    /**
     * 定义ShiRo的生命周期
     * @return
     */
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }
}

 

一般情况下,我们用shiro都会自己去实现Realm和过滤器来控制权限

 

3.实现Realm

package cn.et.demo03.config;

import cn.et.demo03.mapper.UserMapper;
import cn.et.demo03.model.UserInfoModel;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Set;

@Component
public class MyRealm extends AuthorizingRealm {
    @Autowired
    private UserMapper userInfoMapper;

    /**
     * 获取当前用户的权限
     * 将当前用户在数据库的角色的权限 加载到AuthorizationInfo
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String userName =principals.getPrimaryPrincipal().toString();
        Set<String> roleList =userInfoMapper.getRoleByUserName(userName);

        //角色集合对象
        SimpleAuthorizationInfo sai =new SimpleAuthorizationInfo();
        sai.setRoles(roleList);
        return sai;
    }

    /**
     * 认证
     * 将登陆输入的用户名和密码跟数据库里面的用户名密码对比 是否相等
     * 返回值 null表示认证失败 非null认证通过
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //页面传入的token
        UsernamePasswordToken upt =(UsernamePasswordToken)token;
        UserInfoModel queryUser =userInfoMapper.getUserByUserName(token.getPrincipal().toString());

        if (queryUser !=null && queryUser.getPassword().equals(new String(upt.getPassword()))) {
            SimpleAccount sa =new SimpleAccount(upt.getUsername(),upt.getPassword(),"MyDbRealm");
            return sa;
        }
        return null;
    }
}

 

4.实现过滤器

package cn.et.demo03.config;


import cn.et.demo03.mapper.MenuMapper;
import cn.et.demo03.model.MenuModel;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

@Component
public class MyFilter extends AuthorizationFilter {
    @Autowired
    private MenuMapper menuMapper;
    /**
     * 匹配指定过滤器规则的url
     * @param regex
     * @param url
     * @return
     */
    public static boolean matchUrl(String regex,String url){
        regex=regex.replaceAll("/+", "/");
        if(regex.equals(url)){
            return true;
        }
        regex=regex.replaceAll("\\.", "\\\\.");
        // /login.html  /l*.html
        regex=regex.replaceAll("\\*", ".*");
        // /**/login.html  /a/b/login.html
        if(regex.indexOf("/.*.*/")>=0){
            regex=regex.replaceAll("/\\.\\*\\.\\*/", "((/.*/)+|/)");
        }
        System.out.println(regex+"----"+url);
        return Pattern.matches(regex, url);
    }

    /**
     * isAccessAllowed用于判断当前url的请求是否能验证通过  如果验证失败 调用父类的onAccessDenied决定跳转到登录失败页还是授权失败页面
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)throws Exception {
        HttpServletRequest req=(HttpServletRequest)request;

        //获取用户访问的资源路径
        String url=req.getRequestURI();

        //获取哪些url需要哪些认证
        List<MenuModel> list = menuMapper.getMenuByUrl(url);

        //数据库没有配置当前url的授权
        if (list.size()==0) {
            return false;
        }

        String urlAuth=null;
        for (MenuModel menu : list) {
            if (matchUrl(menu.getUrl(), url)) {
                urlAuth =menu.getFilter();
            }
        }

        if(urlAuth==null){
            return false;
        }
        //配置的过滤器是anon 直接放过
        if(urlAuth.startsWith("anon")){
            return true;
        }
        //配置的是authc 判断当前用户是否认证通过
        Subject subject = getSubject(request, response);
        if(urlAuth.startsWith("authc")){
            return subject.isAuthenticated();
        }
        //授权认证 也需要判断是否登录 没有登录返回 登录继续下面的验证
        boolean ifAuthc=subject.isAuthenticated();

        if(!ifAuthc){
            return ifAuthc;
        }

        //如果是定义的roles过滤器  获取所有的roles 一般是roles[a,b]
        if(urlAuth.startsWith("roles")){
            String[] rolesArray=urlAuth.split("roles\\[")[1].split("\\]")[0].split(",");
            if (rolesArray == null || rolesArray.length == 0) {
                return true;
            }
            Set<String> roles = CollectionUtils.asSet(rolesArray);
            return subject.hasAllRoles(roles);
        }
        if(urlAuth.startsWith("perms")){
            String[] perms=urlAuth.split("perms\\[")[1].split("\\]")[0].split(",");
            boolean isPermitted = true;
            if (perms != null && perms.length > 0) {
                if (perms.length == 1) {
                    if (!subject.isPermitted(perms[0])) {
                        isPermitted = false;
                    }
                } else {
                    if (!subject.isPermittedAll(perms)) {
                        isPermitted = false;
                    }
                }
            }
            return isPermitted;
        }
        return false;
    }

}

 

5.编写一个测试类

package cn.et.demo03.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("demo03")
public class ShiRoController {

    @RequestMapping("login")
    public String login(String userName, String password){
        //获取当前的用户
        Subject currentUser =SecurityUtils.getSubject();

        //用户输入的用户名跟密码
        UsernamePasswordToken token = new UsernamePasswordToken(userName, password);

        try {
            currentUser.login( token );
            return "/LoginSuccess.jsp";
        } catch (UnknownAccountException uae) {
            System.out.println("用户名不存在:" + token.getPrincipal());
        } catch (IncorrectCredentialsException ice) {
            System.out.println("密码不正确!!");
        } catch (LockedAccountException lae) {
            System.out.println("用户已被锁定!!");
        }
        return "/LoginError.jsp";
    }
}

 

6.添加一个springboot启动类

package cn.et;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

//必须添加 @SpringBootApplication 启动spring的自动配置功能 必须要添加
@SpringBootApplication

//扫描mapper包 一般用于全局 (推荐使用) 或许在每个类上面加 @Mapper注解效果等价
@MapperScan("cn.et.**.mapper")

public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
}

以上就是在springboot使用shiro控制权限的核心代码。。。。。。。。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值