shriojava代碼 java shrio

Spring Boot整合Shiro實(shí)現(xiàn)前后端分離

??Apache Shiro是Java的一個(gè)安全框架。功能強(qiáng)大,使用簡(jiǎn)單的Java安全框架,它為開(kāi)發(fā)人員提供一個(gè)直觀而全面的認(rèn)證,授權(quán),加密及會(huì)話管理的解決方案。

創(chuàng)新互聯(lián)公司是創(chuàng)新、創(chuàng)意、研發(fā)型一體的綜合型網(wǎng)站建設(shè)公司,自成立以來(lái)公司不斷探索創(chuàng)新,始終堅(jiān)持為客戶提供滿意周到的服務(wù),在本地打下了良好的口碑,在過(guò)去的10余年時(shí)間我們累計(jì)服務(wù)了上千家以及全國(guó)政企客戶,如成都被動(dòng)防護(hù)網(wǎng)等企業(yè)單位,完善的項(xiàng)目管理流程,嚴(yán)格把控項(xiàng)目進(jìn)度與質(zhì)量監(jiān)控加上過(guò)硬的技術(shù)實(shí)力獲得客戶的一致贊揚(yáng)。

??Shiro基本功能點(diǎn)如下所示:

??Shiro工作流程如下所示:

??Shiro內(nèi)部架構(gòu)如下所示:

??本文實(shí)現(xiàn)源碼如下,歡迎Star和Fork。

??實(shí)現(xiàn)思路:用戶登錄時(shí)生成token信息,設(shè)置過(guò)期時(shí)間,使用Redis存儲(chǔ)。前端調(diào)用接口時(shí)將token作為參數(shù)傳給服務(wù)端,服務(wù)端根據(jù)token信息認(rèn)證用戶。

??自定義AuthFilter過(guò)濾器,繼承AuthenticatingFilter重寫(xiě)createToken、isAccessAllowed、onAccessDenied、onLoginFailure方法。

??AuthenticatingFilte類(lèi)executeLogin方法如下所示:

??用戶登錄時(shí)刪除舊Token信息,重新生成Token信息,退出登錄時(shí)刪除Token信息。 使用Redis存儲(chǔ)Token信息時(shí),同時(shí)存儲(chǔ)已用戶ID為鍵,Token為值和已Token為鍵、用戶ID為值的信息 。

??整體實(shí)現(xiàn)流程圖如下所示, 圖源來(lái)自參考鏈接一,侵刪 。

??實(shí)現(xiàn)思路:自定義ModularRealmAuthenticator管理多Realm,結(jié)合自定義認(rèn)證Token關(guān)聯(lián)不同的Realm。

??SecurityManager和ModularRealmAuthenticator配置如下:

??自定義認(rèn)證Token,重寫(xiě)getCredentials方法, 根據(jù)loginType返回不同的比較對(duì)象 。

??普通登陸Realm認(rèn)證邏輯如下所示:

??Token關(guān)聯(lián)的Realm認(rèn)證邏輯如下所示:

??自定義ModularRealmAuthenticator,管理多Realm,實(shí)現(xiàn)邏輯如下所示:

??用戶登錄,返回生成的token信息:

??用戶攜帶token信息查詢文章( 有對(duì)應(yīng)權(quán)限 ):

??用戶攜帶token信息刪除用戶( 無(wú)權(quán)限 ):

??用戶攜帶token信息退出登錄:

??用戶退出登錄后攜帶原token信息刪除用戶:

如何正確的使用shiro

從來(lái)沒(méi)接觸過(guò)shiro Java安全框架,突然有一天需要要用用戶登陸驗(yàn)證和用戶角色權(quán)限的任務(wù),而且是針對(duì)shiro 進(jìn)行整合,開(kāi)始收到任務(wù),心都有點(diǎn)涼涼的。經(jīng)過(guò)一輪的搜索,感覺(jué)沒(méi)多大的收獲。很多用戶的角色都是寫(xiě)在xml配置文件中。覺(jué)得太不人性化了,想換個(gè)用戶角色還得改xml?我覺(jué)得這么強(qiáng)大的框架應(yīng)該不可能這么狗血的存在。然后認(rèn)真的看文檔,發(fā)現(xiàn)真的是可以直接讀取數(shù)據(jù)庫(kù)的。我把我搭建的流程發(fā)布在此。有問(wèn)題的可以交流交流。我寫(xiě)的也并不是正確的,只能參考參考。

1.web.xml的配置

listener

listener-classorg.apache.shiro.web.env.EnvironmentLoaderListener/listener-class

/listener

filter

filter-nameshiroFilter/filter-name

filter-classorg.apache.shiro.web.servlet.ShiroFilter/filter-class

/filter

filter-mapping

filter-nameshiroFilter/filter-name

url-pattern/*/url-pattern

/filter-mapping

2.shiro.ini配置

[main]

[filters]

#自定義realm

shiroAuthorizingRealm = com.frame.security.ShiroAuthorizingRealm

securityManager.realm = $shiroAuthorizingRealm

# 聲明一個(gè)自定義的用戶校驗(yàn)攔截器

customFormAuthenticationFilter = com.frame.security.CustomFormAuthenticationFilter

# 聲明一個(gè)自定義的用戶角色權(quán)限攔截器

customPermissionsAuthorizationFilter = com.frame.security.CustomPermissionsAuthorizationFilter

#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/** = customFormAuthenticationFilter,customPermissionsAuthorizationFilter

從shiro.ini配置中可以看出,需要三個(gè)文件,分別為ShiroAuthorizingRealm.java(realm文件),CustomFormAuthenticationFilter.java(自定義用戶登陸驗(yàn)證文件),CustomPermissionsAuthorizationFilter(自定義用戶角色權(quán)限文件);

在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.dao.findFirst("select * from m_user where account = ?", username);

if (user != null) {//下面可以做一些登陸的操作,密碼錯(cuò)誤,用戶狀態(tài)等等

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){//從數(shù)據(jù)庫(kù)中讀取用戶的角色權(quán)限,

SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

ListString perms = authorityService.getUrlByUser(user);

if(perms!=nullperms.size()0){//調(diào)用addStringPermissions方法把用戶的權(quán)限信息添加到info中,可以addRoles方法把用戶的角色添加到了info中

info.addStringPermissions(perms);

}

return info;

}

return null;

}

}

5.CustomFormAuthenticationFilter.java

public class CustomFormAuthenticationFilter extends FormAuthenticationFilter {

private final static Logger log = Logger.getLogger(CustomFormAuthenticationFilter.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 {

ResultObject result = new ResultObject(false, "401", "沒(méi)有授權(quán),請(qǐng)先登錄", 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.CustomPermissionsAuthorizationFilter.java

public class CustomPermissionsAuthorizationFilter extends PermissionsAuthorizationFilter {

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 {

ResultObject result = new ResultObject(false, "401", "抱歉,您沒(méi)有該權(quán)限!", null);

renderJson(httpResponse, result);

return false;

}

}

/**

* 得到mappedValue,相當(dāng)于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};

}

/**

* 根據(jù)訪問(wèn)路徑獲取權(quán)限代碼

* @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("登錄失敗!無(wú)效的賬號(hào)或密碼!");

} catch (IncorrectCredentialsException ie) {

tokens.clear();

renderFailedResult("用戶已注銷(xiāo)!");

} catch(LockedAccountException le){

tokens.clear();

renderFailedResult("賬號(hào)被鎖定!");

} catch (RuntimeException re) {

re.printStackTrace();

tokens.clear();

renderFailedResult("登錄失??!");

}

}

數(shù)據(jù)庫(kù)可以自己去設(shè)計(jì),這里就不提供了。

參照上面的去整合框架,便可以使用了,這樣搭建適合多種框架的整合。

如何使用Shiro實(shí)現(xiàn)不同用戶登錄成功后跳轉(zhuǎn)到不同主頁(yè)

登陸成功后獲取 Subject 對(duì)象.

然后通過(guò) Subject 對(duì)象來(lái)判斷當(dāng)前用戶的角色/權(quán)限, 之后執(zhí)行不同的跳轉(zhuǎn)(直接在LoginAction中做).

我的登陸部分代碼:

Java代碼

UsernamePasswordToken token = new UsernamePasswordToken(name, password);

try {

SecurityUtils.getSubject().login(token);

Subject subject = SecurityUtils.getSubject();

// 這里可以調(diào)用subject 做判斷

System.out.println("--------------------------------------------------------------");

Boolean isadmin = subject.hasRole("admin");

log.info("是否為管理員:"+isadmin);

System.out.println("--------------------------------------------------------------");

String userId = (String)subject.getPrincipal();

User user = userService.getById(userId);

ShiroUser shiroUser = shiroUserService.getByDyId(userId);

if(shiroUser == null){

this.addActionError(getText("login.failure"));

return ERROR;

}else{

int used = shiroUser.getUsed();

if(used == 1){

this.addActionError(getText("login.noused"));

return ERROR;

}

}

Session session = subject.getSession(true);

session.setAttribute(LoginAction.USER_KEY, user);

session.setAttribute(LoginAction.SHIRO_USER_KEY, shiroUser);

log.info("set workflow define to session");

session.setAttribute("ptDefine", WorkflowContext.getPtDefine());

} catch (AuthenticationException e) {

log.info(e.getMessage());

this.addActionError(getText("login.failure"));

}

if (this.hasErrors()) {

log.info("login erro ...");

return ERROR;

}

session如何在java代碼中判斷是否過(guò)期

系統(tǒng)框架使用的springmvc 。。。。

在controller層上做了攔截器,添加了自定義標(biāo)簽,使用了該標(biāo)簽則需要校驗(yàn)session是否過(guò)期,過(guò)期則跳轉(zhuǎn)至登錄頁(yè)面,但是系統(tǒng)用到了shiro,請(qǐng)問(wèn)在java代碼中如何判斷seesion已經(jīng)過(guò)期

Subject currentUser = SecurityUtils.getSubject();

Session session = currentUser.getSession();

//過(guò)期,則跳轉(zhuǎn)登錄頁(yè)面重新登錄

if () { //就是這里不知道如何寫(xiě)?。。。。。。。。。。。。。。。。。。。。?/p>

dosomething;。。。。

shiro配置如下:

!-- 會(huì)話DAO --

bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO"

property name="activeSessionsCacheName" value="shiro-activeSessionCache"/

property name="sessionIdGenerator" ref="sessionIdGenerator"/

/bean

!-- 會(huì)話驗(yàn)證調(diào)度器 --

bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler"

property name="sessionValidationInterval" value="1800000"/

property name="sessionManager" ref="sessionManager"/

/bean

!-- 會(huì)話管理器 --

bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"

property name="globalSessionTimeout" value="1800000"/!-- 回話有效時(shí)間30分鐘 --

property name="deleteInvalidSessions" value="true"/

property name="sessionValidationSchedulerEnabled" value="true"/

property name="sessionValidationScheduler" ref="sessionValidationScheduler"/

property name="sessionDAO" ref="sessionDAO"/

property name="sessionIdCookieEnabled" value="true"/

property name="sessionIdCookie" ref="sessionIdCookie"/

/bean

希望能幫到樓主, 謝謝

當(dāng)前題目:shriojava代碼 java shrio
瀏覽地址:http://muchs.cn/article12/hjdddc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供虛擬主機(jī)、搜索引擎優(yōu)化、網(wǎng)站營(yíng)銷(xiāo)、靜態(tài)網(wǎng)站、App設(shè)計(jì)電子商務(wù)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

小程序開(kāi)發(fā)