1. 關於Shiro,大家知道多少
根據Shiro的設計思路,用戶與角色之前的關系為多對多,角色與許可權之間的關系也是多對多。在資料庫中需要因此建立5張表,分別是用戶表(存儲用戶名,密碼,鹽等)、角色表(角色名稱,相關描述等)、許可權表(許可權名稱,相關描述等)、用戶-角色對應中間表(以用戶ID和角色ID作為聯合主鍵)、角色-許可權對應中間表(以角色ID和許可權ID作為聯合主鍵)
2. spring boot 集成shiro 怎麼動態獲取許可權
spring boot集成shrio 許可權驗證怎麼做 具體要看許可權控制到什麼程度,簡單的單純用spring mvc 也能行,就是麻煩,什麼都要自己寫。如果寫不好,以後也不好擴展,安全性得不到保證。 apache shiro的話,簡單,易用,功能也強大
3. shiro動態url許可權控制為什麼沒有生效
這個只是一個驗證和授權的框架,許可權控制恐怕沒有那麼細的粒度。
可以用 aop 或者 rbac 來進行細粒度許可權控制。
4. shiro許可權控制有哪幾張數據表
根據Shiro的設計思路,用戶與角色之前的關系為多對多,角色與許可權之間的關系也是多對多。在資料庫中需要因此建立5張表,分別是用戶表(存儲用戶名,密碼,鹽等)、角色表(角色名稱,相關描述等)、許可權表(許可權名稱,相關描述等)、用戶-角色對應中間表(以用戶ID和角色ID作為聯合主鍵)、角色-許可權對應中間表(以角色ID和許可權ID作為聯合主鍵)。具體與service的實現本文不提供。
5. 在shiro中怎麼通過用戶名稱與狀態拿取角色相關的許可權集
許可權分配要看你自己設置什麼樣的用戶,
能擁有什麼許可權,如:管理員能瀏覽所有的頁面,
能進行增刪查改,普通用戶只能瀏覽公開的頁面,只能查看,和修改等。 資料庫表設計方面,建議你增加一張許可權表, 許可權表和用戶表建立關系,
6. 如何正確的使用shiro
從來沒接觸過shiro Java安全框架,突然有一天需要要用用戶登陸驗證和用戶角色許可權的任務,而且是針對shiro 進行整合,開始收到任務,心都有點涼涼的。經過一輪的搜索,感覺沒多大的收獲。很多用戶的角色都是寫在xml配置文件中。覺得太不人性化了,想換個用戶角色還得改xml?我覺得這么強大的框架應該不可能這么狗血的存在。然後認真的看文檔,發現真的是可以直接讀取資料庫的。我把我搭建的流程發布在此。有問題的可以交流交流。我寫的也並不是正確的,只能參考參考。
1.web.xml的配置
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2.shiro.ini配置
[main]
[filters]
#自定義realm
shiroAuthorizingRealm = com.frame.security.ShiroAuthorizingRealm
securityManager.realm = $shiroAuthorizingRealm
# 聲明一個自定義的用戶校驗攔截器
= com.frame.security.
# 聲明一個自定義的用戶角色許可權攔截器
= com.frame.security.
#cache
shiroCacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
shiroCacheManager.cacheManagerConfigFile = classpath:ehcache.xml
securityManager.cacheManager = $shiroCacheManager
#session
sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
sessionManager.sessionDAO = $sessionDAO
securityManager.sessionManager = $sessionManager
securityManager.sessionManager.globalSessionTimeout = 1800000
securityManager = org.apache.shiro.web.mgt.DefaultWebSecurityManager
[urls]
/admin/user/login = anon
/admin/user/logout = anon
/admin/user/registered = anon
/admin/** = ,
從shiro.ini配置中可以看出,需要三個文件,分別為ShiroAuthorizingRealm.java(realm文件),.java(自定義用戶登陸驗證文件),(自定義用戶角色許可權文件);
在urls配置中可以看出不需要攔截的url後面加上anon便可,但有先後順序。
緩存是使用ehcache
3.ehcache.xml配置
<cache name="defaultCache" maxElementsInMemory="500"
maxElementsOnDisk="10000000" eternal="true" overflowToDisk="true"
diskSpoolBufferSizeMB="50" />
<cache name="shiro-activeSessionCache" maxElementsInMemory="500"
maxElementsOnDisk="10000000" eternal="true" overflowToDisk="true"
diskSpoolBufferSizeMB="50" />
<cache name="jdbcRealm.authorizationCache" maxElementsInMemory="500"
maxElementsOnDisk="10000000" eternal="true" overflowToDisk="true"
diskSpoolBufferSizeMB="50" />
<cache name="authorization" maxElementsInMemory="500"
timeToLiveSeconds="3600" eternal="false" overflowToDisk="false" />
4.ShiroAuthorizingRealm.java
public class ShiroAuthorizingRealm extends AuthorizingRealm {
private AuthorityService authorityService = FrameContext.getBean(AuthorityService.class);
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("=======doGetAuthenticationInfo=======");
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
String username = userToken.getUsername();
String password = String.valueOf(userToken.getPassword());
User user = User..findFirst("select * from m_user where account = ?", username);
if (user != null) {//下面可以做一些登陸的操作,密碼錯誤,用戶狀態等等
if(MD5Encoder.validPassword(password, user.getPassword())==false){
throw new UnknownAccountException();
}
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
return info;
} else {
return null;
}
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("=======doGetAuthorizationInfo=======");
User user = (User) principals.getPrimaryPrincipal();
if(user!=null){//從資料庫中讀取用戶的角色許可權,
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
List<String> perms = authorityService.getUrlByUser(user);
if(perms!=null&&perms.size()>0){//調用addStringPermissions方法把用戶的許可權信息添加到info中,可以addRoles方法把用戶的角色添加到了info中
info.addStringPermissions(perms);
}
return info;
}
return null;
}
}
5..java
public class extends FormAuthenticationFilter {
private final static Logger log = Logger.getLogger(.class);
private static final String contentType = "application/json; charset=UTF-8";
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpRequest = WebUtils.toHttp(request);
HttpServletResponse httpResponse = WebUtils.toHttp(response);
if (isLoginRequest(request, response)) {
if (isLoginSubmission(request, response)) {
if (log.isTraceEnabled()) {
log.trace("Login submission detected. Attempting to execute login.");
}
return executeLogin(request, response);
} else {
if (log.isTraceEnabled()) {
log.trace("Login page view.");
}
return true;
}
} else {
Result<Object> result = new Result<Object>(false, "401", "沒有授權,請先登錄", null);
renderJson(httpResponse, result);
return false;
}
}
private void renderJson(HttpServletResponse response, Object object) {
String jsonText = JsonKit.toJson(object);
PrintWriter writer = null;
try {
response.setHeader("Pragma", "no-cache"); // HTTP/1.0 caches might not implement Cache-Control and might only implement Pragma: no-cache
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType(contentType);
writer = response.getWriter();
writer.write(jsonText);
writer.flush();
} catch (IOException e) {
throw new RenderException(e);
}
finally {
if (writer != null) {
writer.close();
}
}
}
}
6..java
public class extends {
private static final String contentType = "application/json; charset=UTF-8";
private AuthorityService authorityService = McmsContext.getBean(AuthorityService.class);
@Override
public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
if(getMappedValue(request)!=null){
return super.isAccessAllowed(request, response, getMappedValue(request));
}
return false;
}
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
// TODO Auto-generated method stub
HttpServletRequest httpRequest = WebUtils.toHttp(request);
HttpServletResponse httpResponse = WebUtils.toHttp(response);
String path = httpRequest.getServletPath();
Subject subject = getSubject(request, response);
if (subject.isPermitted(path)) {
return true;
} else {
Result<Object> result = new Result<Object>(false, "401", "抱歉,您沒有該許可權!", null);
renderJson(httpResponse, result);
return false;
}
}
/**
* 得到mappedValue,相當於perms[user:add]中的「user:add」
* @param path
* @return
*/
public String[] getMappedValue(ServletRequest request) {
HttpServletRequest req = (HttpServletRequest) request;
String path = req.getServletPath();
String code = getCodesByPath(path);
if(null == code) {
return null;
}
return new String[]{code};
}
/**
* 根據訪問路徑獲取許可權代碼
* @param path
* @return
*/
public String getCodesByPath(String path) {
User user = (User) SecurityUtils.getSubject().getPrincipal();
String pers = authorityService.getUrlByUserPath(path,user);
return Optional.ofNullable(pers).orElse(null);
}
private void renderJson(HttpServletResponse response, Object object) {
String jsonText = JsonKit.toJson(object);
PrintWriter writer = null;
try {
response.setHeader("Pragma", "no-cache"); // HTTP/1.0 caches might not implement Cache-Control and might only implement Pragma: no-cache
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType(contentType);
writer = response.getWriter();
writer.write(jsonText);
writer.flush();
} catch (IOException e) {
throw new RenderException(e);
}
finally {
if (writer != null) {
writer.close();
}
}
}
}
7.用戶登陸入口
public void login() {
String account = getPara("account");
String password = getPara("password");
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken tokens = new UsernamePasswordToken(account, password);
tokens.setRememberMe(false);
try {
subject.login(tokens);
User user = (User) subject.getPrincipal();
loginSuccess(user);
UserVo userVo = convertToUserVO(user);
renderSucessResult(userVo);
} catch (UnknownAccountException ue) {
tokens.clear();
renderFailedResult("登錄失敗!無效的賬號或密碼!");
} catch (IncorrectCredentialsException ie) {
tokens.clear();
renderFailedResult("用戶已注銷!");
} catch(LockedAccountException le){
tokens.clear();
renderFailedResult("賬號被鎖定!");
} catch (RuntimeException re) {
re.printStackTrace();
tokens.clear();
renderFailedResult("登錄失敗!");
}
}
資料庫可以自己去設計,這里就不提供了。
參照上面的去整合框架,便可以使用了,這樣搭建適合多種框架的整合。
7. 用shiro做許可權控制要怎麼配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class MyJdbcAuthzService implements JdbcAuthzService {
@Override
public Map<String, AuthzHandler> getJdbcAuthz() {
//載入資料庫的url配置
Map<String, AuthzHandler> authzJdbcMaps = new HashMap<String, AuthzHandler>();
// Map<String, AuthzHandler> authzJdbcMaps = new TreeMap<String, AuthzHandler>(
// new Comparator<String>() {
// public int compare(String k1, String k2) {
// return new Integer(k2.length()).compareTo(k1.length());
// }
//
// });
//遍歷角色
List<Role> roles = Role..findAll();
List<Permission> permissions = null;
for (Role role : roles) {
//角色可用
if (role.getDate("daleted_at") == null) {
permissions = Permission..findByRole("", role.get("id"));
//遍歷許可權
for (Permission permission : permissions) {
//許可權可用
if (permission.getDate("daleted_at") == null) {
if (permission.getStr("url") != null && !permission.getStr("url").isEmpty()) {
authzJdbcMaps.put(permission.getStr("url"), new JdbcPermissionAuthzHandler(permission.getStr("value")));
}
}
}
}
}
return authzJdbcMaps;
}
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
--create role--
INSERT INTO sec_role(id,name, value, intro, pid,left_code,right_code,created_at)
VALUES (sec_role_id_seq.nextval,'超級管理員','R_ADMIN','',0,1,8, current_timestamp),
(sec_role_id_seq.nextval,'系統管理員','R_MANAGER','',1,2,7,current_timestamp),
(sec_role_id_seq.nextval,'會員','R_MEMBER','',2,3,4,current_timestamp),
(sec_role_id_seq.nextval,'普通用戶','R_USER','',2,5,6,current_timestamp);
--create permission--
INSERT INTO sec_permission(id, name, value, url, intro,pid,left_code,right_code, created_at)
VALUES (sec_permission_id_seq.nextval,'管理員目錄','P_D_ADMIN','/admin/**','',0,1,6,current_timestamp),
(sec_permission_id_seq.nextval,'角色許可權管理','P_ROLE','/admin/role/**','',1,2,3,current_timestamp),
(sec_permission_id_seq.nextval,'用戶管理','P_USER','/admin/user/**','',1,4,5,current_timestamp),
(sec_permission_id_seq.nextval,'會員目錄','P_D_MEMBER','/member/**','',0,9,10,current_timestamp),
(sec_permission_id_seq.nextval,'普通用戶目錄','P_D_USER','/user/**','',0,11,12,current_timestamp);
//如果系統不重啟需要載入新許可權到全局過濾
ShiroKit.addJdbcAuthz(authority.getStr("url"),authority.getStr("auth_key"));
8. shiro框架 RequiresPermissions註解怎麼動態配置
這個沒法動態,動態建議您用自定義Filter攔截後再處理。
推薦一套完整的Shiro Demo,免費的。
ShiroDemo:http://www.sojson.com/shiro
Demo已經部署到線上,地址是http://shiro.itboy.net
管理員帳號:admin,密碼:sojson.com 如果密碼錯誤,請用sojson。PS:你可以注冊自己的帳號,然後用管理員賦許可權給你自己的帳號,但是,每20分鍾會把數據初始化一次。建議自己下載源碼,讓Demo跑起來,然後跑的更快。