专注Java教育14年 全国咨询/投诉热线:444-1124-454
星辉LOGO图
始于2009,口口相传的Java黄埔军校
首页 hot资讯 SpringBoot中Shiro权限管理的集成使用

SpringBoot中Shiro权限管理的集成使用

更新时间:2021-11-16 10:14:39 来源:星辉 浏览697次

SpringBoot中Shiro权限管理的集成使用

关键词: Shiro Apache Java JSP

在集成Shiro时,我们首先需要确定我们的步骤:

1.添加Shiro的依赖包,实现自己的Realm类(通过继承AuthorizingRealm类);

2.实现Shiro的配置类

3.实现前端登录界面和Controller类

步骤1:

在 pom.xml 中添加依赖包

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

实现 Realm 类

package ariky.shiro.realm;
import java.util.HashSet;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
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.apache.shiro.util.ByteSource;
import org.apache.shiro.web.subject.WebSubject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; 
/**
* @ClassName:
* @Description: Realm Configuration
* @author fuweilian
* @date 2018-5-12 11:36:41 am
 */
public class MyShiroRealm extends AuthorizingRealm {
    //slf4j records logs, which can not be used
    private Logger logger = LoggerFactory.getLogger(MyShiroRealm.class); 
    /**
     * Set authorization information
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        logger.info("Start authorization(doGetAuthorizationInfo)");
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        HttpServletRequest request = (HttpServletRequest) ((WebSubject) SecurityUtils
                .getSubject()).getServletRequest();//This can be used to obtain other additional parameter information submitted during login
        String username = (String) principals.getPrimaryPrincipal();//This is the demo written here. Later, in the actual project, traditional Chinese medicine obtains the user's role and authority through the login account. This is written dead
        //Acceptance authority
        //role
        Set<String> roles = new HashSet<String>();
        roles.add("role1");
        authorizationInfo.setRoles(roles);
        //Jurisdiction
        Set<String> permissions = new HashSet<String>();
        permissions.add("user:list");
        //permissions.add("user:add");
        authorizationInfo.setStringPermissions(permissions);
        return authorizationInfo;
    } 
    /**
     * Set authentication information
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken authenticationToken) throws AuthenticationException {
        logger.info("Start certification(doGetAuthenticationInfo)");
        //UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        HttpServletRequest request = (HttpServletRequest) ((WebSubject) SecurityUtils
                .getSubject()).getServletRequest();
        UsernamePasswordToken token = new UsernamePasswordToken (request.getParameter("userName"),request.getParameter("password"));
        //Get the account entered by the user
        String userName = (String)token.getPrincipal();
        //Go to the database to match the user information through userName, and do the following processing by querying the user's situation
        //Write it dead for the time being, and deal with it according to the login user account
        logger.info("Account number:"+userName);
        if("passwordError".equals(userName)){//Password error
            throw new IncorrectCredentialsException(); 
        }else if("lockAccount".equals(userName)){// User locking
            throw new LockedAccountException(); 
        }else{
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                    userName, //User name
                    "123456", //Password, write dead
                    ByteSource.Util.bytes(userName+"salt"),//salt=username+salt
                    getName()  //realm name
            );
            return authenticationInfo;
        }
    }    
}

第二步是实现Shiro的配置类:

package ariky.shiro.configuration; 
import java.util.LinkedHashMap;
import java.util.Map; 
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; 
import ariky.shiro.realm.MyShiroRealm; 
/**
* @ClassName: ShiroConfiguration 
* @Description: shiro Configuration class 
* @author fuweilian
* @date 2018-5-12 11:05:09 am
 */
@Configuration
public class ShiroConfiguration {
    private static Logger logger = LoggerFactory.getLogger(ShiroConfiguration.class);
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){
        logger.info("Get into shiroFilter......");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //Set a path that does not need to be blocked
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        //Judge in order
        filterChainDefinitionMap.put("/static/**", "anon");
        //Configure the exit filter, the specific exit code Shiro has implemented for us
        filterChainDefinitionMap.put("/logout", "logout");
        //<!-- authc:All URLs must be authenticated to be accessible; anon: all URLs can be accessed anonymously -- >
        /************************************Initialize all permission information start******************************************/
        //Here, if you want to use it in a project later, you can query it directly from the database
        filterChainDefinitionMap.put("/user/list", "authc,perms[user:list]");
        //filterChainDefinitionMap.put("/user/add", "authc,perms[user:add]");
        /***************************************Initialization of all permission information begins and ends*********************************************/
        filterChainDefinitionMap.put("/**", "authc");
        // If it is not set, it will automatically find the "/ login.jsp" page in the root directory of the Web project
        shiroFilterFactoryBean.setLoginUrl("/login");
        // Link to jump after successful login
        shiroFilterFactoryBean.setSuccessUrl("/index");
        //Unauthorized interface
        shiroFilterFactoryBean.setUnauthorizedUrl("/error/403");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }    
    @Bean
    public MyShiroRealm myShiroRealm(){
         MyShiroRealm myShiroRealm = new MyShiroRealm();
         //You can set the caching mechanism here later
         return myShiroRealm;
    }     
    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }    
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }    
}

第三步:实现驱逐舰类。这里写了两个类。一个是登录信息的LoginController处理类,另一个是测试权限的UserController

1.登录控制器.java

package ariky.controller; 
import java.util.Map; 
import javax.servlet.http.HttpServletRequest; 
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; 
/**
* @ClassName: LoginController 
* @Description: controller of login control
* @author fuweilian
* @date 2018-5-12 01:15:46 PM
 */
@RequestMapping
@Controller
public class LoginController {
    private Logger logger = LoggerFactory.getLogger(LoginController.class);    
    @RequestMapping(value="/login",method=RequestMethod.GET)
    public String getLogin(){
        logger.info("Get into login page");
        return "login";
    }    
    @RequestMapping(value="/login",method=RequestMethod.POST)
    public String doLogin(HttpServletRequest req,Map<String, Object> model){
        logger.info("Enter login processing");
        String exceptionClassName = (String) req.getAttribute("shiroLoginFailure");
        logger.info("exceptionClassName:"+exceptionClassName);
        String error = null;
        if (UnknownAccountException.class.getName().equals(exceptionClassName)) {
            error = "User name/Password error";
        } else if (IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {
            error = "User name/Password error";
        }else if(LockedAccountException.class.getName().equals(exceptionClassName)){ 
            error = "User locked or deleted";
        }else if (exceptionClassName != null) {
            error = "Other errors:" + exceptionClassName;
        }
        if(SecurityUtils.getSubject().isAuthenticated()){//There is no error, but you have already signed in, and you can directly jump to the welcom page
            model.put("name", req.getParameter("userName"));
            return "index";
        }else{//Erroneous
            model.put("error", error);
            return "login";
        }
    }
    @RequestMapping("/index")
    public String index(){
        return "index";
    }
}

2.UserController.java

package ariky.controller; 
import java.util.ArrayList;
import java.util.List; 
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody; 
/**
* @ClassName: UserController 
* @Description: User processing Controller
* @author fuweilian
* @date 2018-5-12 03:11:06 PM
 */
@Controller
@RequestMapping("/user")
public class UserController {
    Logger logger = LoggerFactory.getLogger(UserController.class);
    @RequiresPermissions("user:list")//This is to configure whether this permission is available. If it is written according to the above method, this permission is available
    @RequestMapping(value="/list",method=RequestMethod.GET)
    public String getList(){
        logger.info("Enter user list");
        return "user/list";
    }
    @RequiresPermissions(value={"user:add"})//This is not authorized
    @RequestMapping(value="/add",method=RequestMethod.GET)
    public String getAdd(){
        logger.info("Enter the new user interface");
        return "user/add";
    }    
}

前端接口:有五个接口(login.jsp、index.jsp、list.jsp、add.jsp、403.jsp)

目录结构为:

1.登录.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Login</title>
</head> 
<body>
    <h1>Login page----${error}</h1>
    <form:form action="${pageContext.request.contextPath }/login"
         method="post">
        User name:<input type="text" name="userName">
        <br />
        Password:<input type="passwordParam" name="password"/>
        <input type="submit" value="Submission"/>
    </form:form>
</body>
</html>

2.index.jsp

<%@ page language="java" pageEncoding="UTF-8"%>
 <%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>First example</title>
<script src="${pageContext.request.contextPath }/webjars/jquery/2.1.4/jquery.js"></script>
<script src="${pageContext.request.contextPath }/webjarslocator/jquery/jquery.js"></script>
</head> 
<body>
    <h1>${name}:Hello, welcome to this website</h1>
        <shiro:hasPermission name="user:list"><!-- this a The label is visible -->
            <a href="${pageContext.request.contextPath }/user/list" target="_blank">Jump to user list(Have jurisdiction)</a>
        </shiro:hasPermission>
    <br/>
        <shiro:hasPermission name="user:add"><!-- this a The label is invisible -->
            <a href="${pageContext.request.contextPath }/user/add" target="_blank">Jump to new user list(No authority)</a>
        </shiro:hasPermission>
</body>
</html>

3.list.jsp 与 add.jsp 和 403.jsp 几乎相同。这是一个。这只是为了演示。在实际项目中,以实际项目为准

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>userList</title>
</head> 
<body>
    <h1>User list information</h1>
</body>
</html>

如果启动成功,就可以进入登录登录界面测试shiro的权限认证。上面的代码都是写死的。如果要实现动态权限管理和用户权限管理,还需要做一些其他的处理。用户的动态权限只需要在他的ShiroRealm类中授权就可以查询数据库,动态授权和角色就可以了。对于动态权限管理,可以实现以下方法。修改权限数据后,只需更新shiro中的配置即可。具体看下面的代码。这是演示,而不是实际项目。在实际项目中,最好不要在Controller中写逻辑

package ariky.shiro.controller; 
import java.util.LinkedHashMap;
import java.util.Map; 
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; 
/**
* @ClassName: PermssionController 
* @Description: controller of permission Operation 
* @author fuweilian
* @date 2018-5-12 04:59:15 PM
 */
@Controller
@RequestMapping("permssion")
public class PermssionController {    
     @Autowired
     ShiroFilterFactoryBean shiroFilterFactoryBean;     
     /**
     * @Title: updatePermssion 
     * @author: fuweilian
     * @Description: This is written in the controller for the time being. It is not written according to the rules. It will be written when it is used in the project
     * @return  Parameter description 
     * @return Object    Return type 
     * @throws
      */
    @RequestMapping("/updatePermssion")
    @ResponseBody
    public Object updatePermssion(){
        synchronized (shiroFilterFactoryBean){
            AbstractShiroFilter shiroFilter = null;
            try {
                shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean
                        .getObject();
                PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter
                    .getFilterChainResolver();
                DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver
                    .getFilterChainManager();
                // Clear old permission control
                manager.getFilterChains().clear();
                shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();
                //The latter one can be obtained directly from the database
                Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
                //Judge in order
                filterChainDefinitionMap.put("/static/**", "anon");
                //Configure the exit filter, the specific exit code Shiro has implemented for us
                filterChainDefinitionMap.put("/logout", "logout");
                //<!-- authc:All URLs must be authenticated to be accessible; anon: all URLs can be accessed anonymously -- >
                /************************************Initialize all permission information start******************************************/
                //Here, if you want to use it in a project later, you can query it directly from the database
                filterChainDefinitionMap.put("/user/list", "authc,perms[user:list]");
                filterChainDefinitionMap.put("/user/add", "authc,perms[user:add]");
                /***************************************Initialization of all permission information begins and ends*********************************************/
                filterChainDefinitionMap.put("/**", "authc");
                //
                shiroFilterFactoryBean.setLoginUrl("/login");
                // Link to jump after successful login
                shiroFilterFactoryBean.setSuccessUrl("/index");
                //Unauthorized interface
                shiroFilterFactoryBean.setUnauthorizedUrl("/error/403");
                shiroFilterFactoryBean
                    .setFilterChainDefinitionMap(filterChainDefinitionMap);
                // Rebuild build
                Map<String, String> chains = shiroFilterFactoryBean
                        .getFilterChainDefinitionMap();
                for (Map.Entry<String, String> entry : chains.entrySet()) {
                    String url = entry.getKey();
                    String chainDefinition = entry.getValue().trim()
                            .replace(" ", "");
                    manager.createChain(url, chainDefinition);
                }
                return "Update permission succeeded";  
            } catch (Exception e) {
                throw new RuntimeException(
                        "To update shiro Permission error!");
            }
        }
    } 
}

以上就是关于“SpringBoot中Shiro权限管理的集成使用”的介绍,如果您对此比较感兴趣,想了解更多相关知识,不妨来关注一下星辉的Shiro视频教程,里面的内容详细,通俗易懂,适合小白学习,希望对大家能够有所帮助。

提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>