海南網(wǎng)站建設(shè)服務(wù)外貿(mào)谷歌seo
?一、權(quán)限基礎(chǔ)
a) 認(rèn)證(你是誰?)
判斷你(被認(rèn)證者)是誰的過程。通常被認(rèn)證者提供用戶名和密碼。
常見的認(rèn)證包含如下幾種:
- 匿名認(rèn)證:允許訪問資源,不做任何類型的安全檢查。
- 表單認(rèn)證:訪問資源之前,需要提交包含用戶名和密碼的表單。這是web application最常用的認(rèn)證方式。這個過程一般會接合Session,只在第一次(新會話)訪問資源時提交認(rèn)證表單。
- 基本HTTP認(rèn)證:基于RFC 2617的一種認(rèn)證方式。
- 用戶認(rèn)證:Filter that allows access to resources if the accessor is a known user, which is defined as having a known principal. This means that any user who is authenticated or remembered via a 'remember me' feature will be allowed access from this filter.
b)? 授權(quán)(你可以做什么?)
判斷被認(rèn)證者(你)是否能做什么操作的過程。
- 端口授權(quán):必須通過指定的某個端口才能訪問資源。
- Permission授權(quán):Filter that allows access if the current user has the permissions specified by the mapped value, or denies access if the user does not have all of the permissions specified.
- Role授權(quán):Filter that allows access if the current user has the roles specified by the mapped value, or denies access if the user does not have all of the roles specified.
perms ????org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
port ????org.apache.shiro.web.filter.authz.PortFilter
roles ????org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
ssl ????org.apache.shiro.web.filter.authz.SslFilter
c)? 加密
使用技術(shù)手段(如:MD5、SHA等)把待加密的數(shù)據(jù)變?yōu)槊芪?#xff08;如:信息摘要等)過程。
d)? RBAC
基于角色的訪問控制(Role-Based Access Control)。
e) Realm
data access object for an application’s security components (users,roles, permissions)
f)? Permission
最小粒度的授權(quán),不與用戶關(guān)聯(lián)。
例如:導(dǎo)出報表、查看id號為“PO20090008”的采購單、創(chuàng)建FAQ。
g) Role
Permission的集合。
二、Shiro特點
- 簡單。
- 功能強(qiáng)大。
- 能獨立運(yùn)行,不依賴其它框架或容器。
- 包含了認(rèn)證、授權(quán)、Session管理、加密。
- 易于擴(kuò)展。
三、web application 集成Shiro
a)? 數(shù)據(jù)模型
用戶賬號Account,可以簡單的理解為用戶。
一個賬號可以擁有多個角色(Role)。
一個角色包含了多個權(quán)限(Permission)。
b)? 創(chuàng)建工程,新建實體,添加與Shiro相關(guān)的Jar包
Eclipse:File--New--Other--Web--Dynamic Web Project
在 /WEB-INFO/lib/目錄下添加如下Jar包
相關(guān)Jar包,http://incubator.apache.org/shiro/download.html
c)? 配置web.xml,添加過濾器
<filter><filter-name>ShiroFilter</filter-name><filter-class>org.apache.shiro.web.servlet.IniShiroFilter</filter-class>
</filter>
<filter-mapping><filter-name>ShiroFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
d)? INI配置
[main]
#SHA256加密
sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher#realm
myRealm = com.xx.xx.shiro.MyShiroRealm
myRealm.credentialsMatcher = $sha256Matcher#緩存
myRealm.authorizationCachingEnabled = true
cache=org.apache.shiro.cache.ehcache.EhCacheManager
myRealm.cacheManager=$cache[filters]
shiro.loginUrl = /login.jsp
#authc=org.apache.shiro.web.filter.authc.FormAuthenticationFilter
authc.successUrl =/background.jsp
perms.unauthorizedUrl =/401.jsp[urls]
/login.jsp=authc
/logout.jsp=anon
/about.jsp=anon
/background.jsp=authc/faq/test.jsp=authc
/faq/list.jsp=authc,perms["faq:list"]
/faq/view.jsp=authc,perms["faq:view"]
位置:
配置參數(shù)可以寫在web.xml文件中,也可以單獨文件形式存放在本地類根路徑、文件系統(tǒng)以及網(wǎng)絡(luò)環(huán)境中。
Shiro INI Inline Config 和External Config
public class MyShiroRealm extends AuthorizingRealm {protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {String username = (String) principals.fromRealm(getName()).iterator().next();if( username != null ){AccountManager accountManager = new AccountManagerImpl();Collection<Role> myRoles = accountManager.getRoles( username );if( myRoles != null ){SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();for( Role each:myRoles ){info.addRole(each.getName());info.addStringPermissions( each.getPermissionsAsString() );}return info;}}return null;}protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken ) throws AuthenticationException {UsernamePasswordToken token = (UsernamePasswordToken) authcToken;String accountName = token.getUsername();//用戶名密碼驗證if( accountName != null && !"".equals(accountName) ){AccountManager accountManager = new AccountManagerImpl();Account account = accountManager.get( token.getUsername() );if( account != null )return new SimpleAuthenticationInfo(account.getName(),account.getPassword(), getName() );}return null;}
}
f)? ?登錄頁面
?<%Object obj = request.getAttribute(org.apache.shiro.web.filter.authc.
FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);boolean flag = false;String msg = "";???????????????????if( obj != null ){if( "org.apache.shiro.authc.UnknownAccountException".equals( obj ) )msg = "未知帳號錯誤!";else if("org.apache.shiro.authc.IncorrectCredentialsException".equals( obj ))msg = "密碼錯誤!";???????????????????else if( "org.apache.shiro.authc.AuthenticationException".equals( obj ))msg = "認(rèn)證失敗!";flag = !"".equals(msg);}???????????if( flag )out.print( msg );
%><form action="login.jsp" method="post"><br/>用戶帳號:<input type="text"??name="username" id="username" value=""/><br/>登錄密碼:<input type="password" name="password" id="password" value="" />????????????????????????????<br/><input value="登錄" type="submit" >
</form>
g)? 登出頁面
<%SecurityUtils.getSubject().logout();%>
四、在Shiro中實現(xiàn)CAPTCHA(驗證碼)功能
a)??驗證碼表單認(rèn)證過濾器
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;public?class?CaptchaFormAuthenticationFilter?extends?FormAuthenticationFilter{public?static?final?String?DEFAULT_CAPTCHA_PARAM?=?"captcha";private?String?captchaParam?=?DEFAULT_CAPTCHA_PARAM;public?String getCaptchaParam() {return?captchaParam;}protected?String getCaptcha(ServletRequest request) {return?WebUtils.getCleanParam(request, getCaptchaParam());}protected?AuthenticationToken createToken(ServletRequest request, ServletResponse response) {String username = getUsername(request);String password = getPassword(request);String captcha = getCaptcha(request);boolean?rememberMe = isRememberMe(request);String host = getHost(request);???????return?new?CaptchaUsernamePasswordToken(username, password, rememberMe, host,captcha);}
}
b)??用戶名密碼令牌UsernamePasswordToken
import org.apache.shiro.authc.UsernamePasswordToken;public?classCaptchaUsernamePasswordToken?extends?UsernamePasswordToken {private?static?final?long?serialVersionUID?= 1L;private?String?captcha;public?String getCaptcha() {return?captcha;} public?void?setCaptcha(String captcha) {this.captcha?= captcha;}public?CaptchaUsernamePasswordToken() {super();}public?CaptchaUsernamePasswordToken(String username,?char[] password,boolean?rememberMe, String host,String captcha) {????????super(username, password, rememberMe, host);this.captcha?= captcha;}
}
c)??添加AuthenticationException
public?classIncorrectCaptchaException?extends?AuthenticationException{private?static?final?long?serialVersionUID?= 1L;public?IncorrectCaptchaException() {super();}public?IncorrectCaptchaException(String message, Throwable cause) {super(message, cause);}public?IncorrectCaptchaException(String message) {super(message);}public?IncorrectCaptchaException(Throwable cause) {super(cause);}
}
d)??Shiro INI文件
authc=?com.xx.xx.shiro.CaptchaFormAuthenticationFilter
e)??實現(xiàn)Realm
?protectedAuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken )?throwsAuthenticationException {CaptchaUsernamePasswordToken token = (CaptchaUsernamePasswordToken) authcToken;String accountName = token.getUsername();//驗證碼?驗證String captcha =?null;Object obj_captcha = SecurityUtils.getSubject().getSession().getAttribute( SessionKey.CAPTCHA?);Object obj_count = SecurityUtils.getSubject().getSession().getAttribute( SessionKey.LOGIN_FAILED_COUNT?);int?failed_count = (obj_count ==?null?|| !(obj_count?instanceof?Integer))?0:(Integer)obj_count;if( obj_captcha?instanceof?String)captcha = (String)obj_captcha;if( captcha !=?null?&& failed_count >0&& !captcha.equalsIgnoreCase( token.getCaptcha() )){throw?newIncorrectCaptchaException("驗證碼錯誤!");}//用戶名密碼驗證if( accountName !=?null?&& !"".equals(accountName) ){AccountManager accountManager =?newAccountManagerImpl();Account account = accountManager.get( token.getUsername() );if( account !=?null?)return?new?SimpleAuthenticationInfo( account.getName(),account.getPassword(), getName() );}return?null;}
}
f)???登錄頁面
<% Object obj = request.getAttribute(org.apache.shiro.web.filter.authc.
FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);boolean?flag =?false;String msg =?"";????????????????????????if( obj !=?null?){if(?"org.apache.shiro.authc.UnknownAccountException".equals( obj ) )msg =?"未知帳號錯誤!";else?if("org.apache.shiro.authc.IncorrectCredentialsException".equals( obj ))msg =?"密碼錯誤!";else?if("com.xx.xx.shiro.IncorrectCaptchaException".equals( obj ))msg =?"驗證碼錯誤!";else?if(?"org.apache.shiro.authc.AuthenticationException".equals( obj ))msg =?"認(rèn)證失敗!";flag = !"".equals(msg);}if( flag ){out.print( msg );Integer count = (Integer)request.getSession().getAttribute(SessionKey.LOGIN_FAILED_COUNT );if( count ==?null?)count = Integer.valueOf(0);count++;request.getSession().setAttribute(SessionKey.LOGIN_FAILED_COUNT, count);}???????????????????
%><form?action="login.jsp"?method="post"><br/>用戶帳號:<input?type="text"??name="username"?id="username"?value=""/><br/>登錄密碼:<input?type="password"?name="password"?id="password"?value=""?/>?????????<br/>驗證碼:<input type="text" name="captcha" id="captcha" size="6"/><img src="/captcha" alt="captcha" /><br/><input?value="登錄"?type="submit"?>
</form>
g)??CAPTCHA實現(xiàn)
h)??????
五、代碼的開發(fā)環(huán)境
JAVA1.6
Tomcat
Eclipse