-
web.xml添加配置web
<!-- shiro過濾器 -->spring<filter>數據庫
<filter-name>shiroFilter</filter-name>apache
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>緩存
<init-param>安全
<param-name>targetFilterLifecycle</param-name>app
<param-value>true</param-value>ide
</init-param>ui
</filter>url
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
-
shiro與spring整合配置
<!-- 使用shiro安全檢查註解 --><bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor" />
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
<!-- shiro的生命週期處理器 --><bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<!-- shiro自帶的密碼匹配器(用來校驗密碼足夠了) -->
<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.SimpleCredentialsMatcher"></bean>
<!-- security datasource: -->
<bean id="myRealm" class="cc.eguid.service.shiro.MyRealm">
<property name="credentialsMatcher" ref="credentialsMatcher"/><!-- 密碼匹配器 -->
<property name="cachingEnabled" value="false"/><!-- 禁止緩存 -->
</bean>
<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm" />
</bean>
<!-- shiro過濾器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 配置安全管理器 -->
<property name="securityManager" ref="securityManager" />
<!-- 身份認證失敗跳轉的地址 -->
<property name="loginUrl" value="/login/" />
<!-- 身份認證成功跳轉的地址 -->
<property name="successUrl" value="/" />
<!-- 權限認證失敗跳轉的地址 -->
<property name="unauthorizedUrl" value="/login/unauthorized" />
<property name="filterChainDefinitions">
<!--anon 表示匿名訪問,不須要認證以及受權 -->
<!--authc表示須要認證 沒有進行身份認證是不能進行訪問的 -->
<!--authc,roles[admin]表示是admin角色的用戶才能訪問 -->
<value>
/static/** = anon
/login/** = anon
/common/** = anon
/admin/** = authc,roles[admin]
/* = authc
/** = authc
</value>
</property>
</bean>
-
realm和自定義密碼校驗器實現
public class MyRealm extends AuthorizingRealm{Logger log=Logger.getLogger(MyRealm.class);
@Autowired
private UserService userService;//這是本身實現的用戶信息操做類,實現用戶信息,用戶角色信息、用戶權限信息查詢功能
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
UserInfo user = (UserInfo) principals.getPrimaryPrincipal();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 查詢角色信息
Collection<String> roles = userService.findRoles(user);
info.addRoles(roles);
log.info("shiro獲取用戶所屬角色列表:"+roles);
// 查詢權限信息
Collection<String> permissions = userService.findPermissions(user.getSystemuserid());
info.addStringPermissions(permissions);
log.info("shiro獲取用戶權限列表:"+permissions);
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)throws AuthenticationException{
//用戶輸入的用戶名密碼
String loginname= token.getPrincipal().toString();
Object password=token.getCredentials();
log.info("shiro正在處理嘗試登陸的用戶信息:"+loginname+",密碼:"+new String((char[])password));
//數據庫中的用戶信息
UserInfo user =userService.queryUserInfoByLoginName(loginname);
if(user==null||CommonUtil.isNull(user.getLoginusername(),user.getPassword(),user.getSystemuserid())){
return null;
}
log.info("shiro獲取到當前用戶嘗試登陸的真實數據:"+user.getLoginusername()+",密碼:"+user.getPassword());
//數據庫中的正確的帳戶信息
AuthenticationInfo accountInfo =new SimpleAuthenticationInfo(user, user.getPassword(),getName());
//本身獲取密碼驗證器(因爲shiro實現的密碼校驗方法是密碼錯誤會直接拋異常,不採用,因此改爲直接手動校驗)
CredentialsMatcher matcher=getCredentialsMatcher();
if(matcher==null){
log.error("沒有配置密碼匹配器");
return null;
}
//校驗密碼
if(matcher.doCredentialsMatch(token,accountInfo)){
return accountInfo;//校驗經過,返回帳號信息
}
return null;
}
}
-
自定義密碼校驗器
/*** 自定義shiro密碼匹配(密碼是在md5散列值的基礎上再次進行md5加鹽操做,加鹽值不保存在數據庫,而是放在配置文件中)
* @author eguid
*
*/
public class MyCredentialsMatcher extends CodecSupport implements CredentialsMatcher {
private static final Logger log = LoggerFactory.getLogger(MyCredentialsMatcher.class);
protected Object getCredentials(AuthenticationToken token) {
return token.getCredentials();
}
protected Object getCredentials(AuthenticationInfo info) {
return info.getCredentials();
}
@Autowired
private CommonConfigs commonConfigs;
/**
* 驗證密碼
*
* @param tokenCredentials
* @param accountCredentials
* @return
*/
protected boolean equals(Object tokenCredentials, Object accountCredentials) {
if (log.isDebugEnabled()) {
log.debug("Performing credentials equality check for tokenCredentials of type ["
+ tokenCredentials.getClass().getName() + " and accountCredentials of type ["
+ accountCredentials.getClass().getName() + "]");
}
if (isByteSource(tokenCredentials) && isByteSource(accountCredentials)) {
if (log.isDebugEnabled()) {
log.debug("Both credentials arguments can be easily converted to byte arrays. Performing "
+ "array equals comparison");
}
byte[] tokenBytes = toBytes(tokenCredentials);
byte[] accountBytes = toBytes(accountCredentials);
return MessageDigest.isEqual(tokenBytes, accountBytes);
} else {
return accountCredentials.equals(tokenCredentials);
}
}
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
Object tokenCredentials = getCredentials(token);
Object accountCredentials = getCredentials(info);
String account=String.valueOf((char[])tokenCredentials);
if(commonConfigs.getMd5salt()==null){
if (log.isDebugEnabled()) {
log.debug("配置文件中的加鹽值爲空,沒法進行密碼匹配,請確認配置文件是否在指定位置或配置指定加鹽值");
}
return false;
}
String saltaccount=MD5Util.getMD5(account, commonConfigs.getMd5salt());
if (log.isDebugEnabled()) {
log.debug("加鹽後的密碼:"+saltaccount);
}
return equals(accountCredentials, saltaccount.toCharArray());
}
}
-
註解使用及模板標籤使用
一、註解使用
@RequiresPermissions({"user:update:view"})//檢查操做權限
@RequiresPermissions(value={"user:add","user:view"},logical=Logical.OR)//兩個操做權限其中一個知足條件便可經過檢查
@RequiresRoles({"admin"})//檢查角色
@RequiresRoles(value={"debug","admin"},logical=Logical.OR)//兩個角色其中一個角色知足條件便可@RequiresAuthentication//檢查是否經過shiro認證
@RequiresGuest//不須要驗證
@RequiresUser//檢查用戶是不是當前系統中的用戶二、標籤使用
使用標籤須要先導入shiro的標籤庫<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
(1)顯示用戶身份信息
<shiro: principal/>
默認調用Subject.getPrincipal()獲取<shiro:principal property="username"/>
至關於((User)Subject.getPrincipals()).getUsername()(2)已登陸shiro用戶顯示
<shiro:user>
歡迎[<shiro:principal/>]登陸,<a href="logout">退出</a>
<shiro:user>(3)匿名用戶訪問
<shiro:guest>未通過shiro驗證的用戶(遊客,匿名用戶)</shiro:guest>(4)已經在shiro登陸過的(已登陸用戶)
<shiro:authenticated>
用戶[<shiro:principal/>]已身份驗證經過
<shiro:authenticated>(5)沒有在shiro登陸過的
<shiro:notAuthenticated>
未身份驗證(包括記住我)
<shiro:notAuthenticated>(6)檢查角色
<shiro:hasRole name="admin">
用戶[<shiro:principal/>]擁有角色admin<br/>
<shiro:hasRole>檢查任意角色(其中一個知足條件即經過,至關於OR)
<shiro:hasAnyRoles name="admin,user">
用戶[<shiro:principal/>]擁有角色admin或user<br/>
<shiro:hasAnyRoles>不具備角色(反向判斷)
<shiro:lacksRole name="abc">
用戶[<shiro:principal/>]不具備角色abc<br/>
<shiro:lacksRole>(7)操做權限判斷
<shiro:hasPermission name="user:create">
用戶[<shiro:principal/>]擁有權限user:create<br/>
<shiro:hasPermission>不具備操做權限(反向判斷)
<shiro:lacksPermission name="org:create">
用戶[<shiro:principal/>]沒有權限org:create<br/>
<iro:lacksPermission>END