注意: 該過濾器須要配置在struts2過濾器以前css
<!-- 配置Shiro的代理過濾器 -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>web
注意:過濾器ShiroFilterFactoryBean的id必須與web.xm中的過濾器name屬性值一致spring
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 注入shiro的安全管理員 -->
<property name="securityManager" ref="securityManager"></property>
<!-- 數據庫
注入登陸路徑apache
loginUrl :沒有登陸的用戶請求須要登陸的頁面時自動跳轉到登陸頁面,不是必須的屬性,安全
不輸入地址的話會自動尋找項目web項目的根目錄下的」/login.jsp」頁面。
session
-->
<property name="loginUrl" value="/login.jsp"></property>
<!-- app
注入登陸成功的路徑jsp
successUrl :登陸成功默認跳轉頁面,不配置則跳轉至」/」。若是登錄前點擊的一個須要登陸的頁面,ide
則在登陸自動跳轉到那個須要登陸的頁面。不跳轉到此。
-->
<property name="successUrl" value="/index.jsp"></property>
<!--
注入權限不足的路徑
unauthorizedUrl :沒有權限默認跳轉的頁面。
-->
<property name="unauthorizedUrl" value="/unauthorizedUrl.jsp"></property>
<!-- url權限級別的控制 -->
<property name="FilterChainDefinitions">
<value>
<!-- 對頁面應用的css文件放行 anon表示不須要任何權限就能訪問 -->
/css/** = anon
<!-- 對頁面應用的js文件放行 -->
/js/** = anon
<!-- 對頁面應用的圖片images文件放行 -->
/images/** = anon
<!-- 對頁面應用的驗證碼jsp文件,jsp後面加*號是在驗證碼jsp後面跟參數也放行 -->
/validatecode.jsp* = anon
<!-- 對頁面應用的登陸頁面放行 -->
/login.jsp* = anon
<!-- 對頁面應用的登陸提交的login.action類放行 -->
/user_login* = anon
<!-- 對訪問staff.action設置權限限制 -->
/page_base_staff.action = perms[staff]
<!-- 對其餘上面沒有設置的路徑設置權限設置 -->
<!-- 過濾器鏈的執行順序是自上而下依次匹配, 若是能匹配上, 則再也不往下匹配 -->
/** = authc
</value>
</property>
</bean>
//登陸功能
public String login () {
HttpServletRequest request = ServletActionContext.getRequest();
//1.驗證碼校驗
String validateCode = (String) request.getSession().getAttribute("key");
if (StringUtils.containsWhitespace(checkcode) || !validateCode.equalsIgnoreCase(checkcode)) {
//1.1若是校驗不成功,跳轉到登陸頁面,並提示"驗證碼不正確的信息"
this.addActionError(this.getText("checkCodeError"));
return "login";
}
//2.若是校驗成功實現登陸功能
//建立subject權限對象
//Subject 是與程序進行交互的對象,能夠是人也能夠是服務或者其餘,一般就理解爲用戶。
//全部Subject 實例都必須綁定到一個SecurityManager上。咱們與一個 Subject 交互,
//運行時shiro會自動轉化爲與 SecurityManager交互的特定 subject的交互。
Subject subject = SecurityUtils.getSubject();
//建立用戶名和密碼的令牌
String username = model.getUsername();
String password = model.getPassword();
password = MD5Utils.md5(password);
AuthenticationToken token = new UsernamePasswordToken(username, password);
//調用安全管理器
try {
subject.login(token);
//從subject中獲取保存在安全管理員中的user對象
User user = (User) subject.getPrincipal();
//將用戶保存在session中,由於自定義攔截器的緣由(若是沒有自定義攔截器, 將用戶存放在session域中的這個步驟能夠省略)
request.getSession().setAttribute("loginUser", user);
} catch (UnknownAccountException e) {
e.printStackTrace();
this.addActionError(this.getText("usernameError"));
return "login";
} catch (AuthenticationException e) {
e.printStackTrace();
this.addActionError(this.getText("passwordError"));
return "login";
}
return "home";
}
public class BOSRealm extends AuthorizingRealm {
@Resource
private IUserDao userDao;
//權限認證
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken paramAuthenticationToken)
throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) paramAuthenticationToken;
String username = token.getUsername();
//調用userdao根據用戶名查詢用戶
User user = userDao.findByUsername(username);
if (user != null) {
//若是查詢的用戶存在
//TODO 與數據庫中用戶名和密碼進行比對。比對成功則返回info,比對失敗則拋出對應信息的異常AuthenticationException
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user,
user.getPassword(), this.getClass().getName());
return authenticationInfo;
} else {
//若是查詢不到用戶, 返回空, Shiro會拋出UnknownAccountException異常
return null;
}
}
//授予權限
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection paramPrincipalCollection) {
// TODO Auto-generated method stub
return null;
}
}
<!-- 7配置Shiro的安全管理器 -->
<bean name="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- 注入realm數據橋 -->
<property name="realm" ref="bosRealm"></property>
</bean>
<!-- 配置Realm數據橋對象 -->
<bean id="bosRealm" class="cn.rodge.bos.shiro.BOSRealm"></bean>
在Shiro權限認證以後, 認證過的用戶對於特定權限的頁面或者功能仍然不具有訪問權限, 此時就須要針對不一樣的用戶進行相應的受權操做. Shiro的受權操做是在權限認證的基礎之上完成的. 須要修改BOSRealm類中的權限授予的方法.
//授予權限
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection paramPrincipalCollection) {
//建立受權信息對象
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//根據當前用戶查詢數據庫,獲取其權限對象
//獲取當前用戶,因爲shiro的過濾器在struts的過濾器以前執行,所以此時的用戶尚未被封裝到session中,
//故獲取當前用戶在session中娶不到
/*Subject subject = SecurityUtils.getSubject();
User loginUser = (User) subject.getPrincipal();*/
User loginUser = (User) paramPrincipalCollection.getPrimaryPrincipal();
if (loginUser != null) {
List<Function> list = null;
//表示用戶存在,調用roledao根據用戶查詢全部權限
if ("admin".equals(loginUser.getUsername())) {
//若是是超級管理員,賦予全部權限
list = functionDao.findAll();
} else {
//根據用戶id查詢全部權限
list = functionDao.findFunctionByUserId(loginUser.getId());
}
if (list != null && list.size() > 0) {
for (Function function : list) {
//爲用戶受權
simpleAuthorizationInfo.addStringPermission(function.getCode());
}
}
return simpleAuthorizationInfo;
} else {
return null;
}
}
@SuppressWarnings("unchecked") @Override //根據用戶id查詢權限 public List<Function> findFunctionByUserId(String id) { String hql = "from Function f left outer join fetch f.roles r " + "left outer join fetch r.users u where u.id = ?"; return this.getHibernateTemplate().find(hql, id); }