更新時間:2021-11-16 10:14:39 來源:動力節(jié)點 瀏覽928次
關(guān)鍵詞: Shiro Apache Java JSP
1.添加Shiro的依賴包,實現(xiàn)自己的Realm類(通過繼承AuthorizingRealm類);
2.實現(xiàn)Shiro的配置類
3.實現(xiàn)前端登錄界面和Controller類
步驟1:
在 pom.xml 中添加依賴包
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
實現(xiàn) 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;
}
}
}
第二步是實現(xiàn)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;
}
}
第三步:實現(xiàn)驅(qū)逐艦類。這里寫了兩個類。一個是登錄信息的LoginController處理類,另一個是測試權(quán)限的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)
目錄結(jié)構(gòu)為:
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 幾乎相同。這是一個。這只是為了演示。在實際項目中,以實際項目為準(zhǔn)
<%@ 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>
如果啟動成功,就可以進(jìn)入登錄登錄界面測試shiro的權(quán)限認(rèn)證。上面的代碼都是寫死的。如果要實現(xiàn)動態(tài)權(quán)限管理和用戶權(quán)限管理,還需要做一些其他的處理。用戶的動態(tài)權(quán)限只需要在他的ShiroRealm類中授權(quán)就可以查詢數(shù)據(jù)庫,動態(tài)授權(quán)和角色就可以了。對于動態(tài)權(quán)限管理,可以實現(xiàn)以下方法。修改權(quán)限數(shù)據(jù)后,只需更新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!");
}
}
}
}
以上就是關(guān)于“SpringBoot中Shiro權(quán)限管理的集成使用”的介紹,如果您對此比較感興趣,想了解更多相關(guān)知識,不妨來關(guān)注一下動力節(jié)點的Shiro視頻教程,里面的內(nèi)容詳細(xì),通俗易懂,適合小白學(xué)習(xí),希望對大家能夠有所幫助。
初級 202925
初級 203221
初級 202629
初級 203743