Shiro權(quán)限框架
開(kāi)發(fā)系統(tǒng)中,少不了權(quán)限,目前java里的權(quán)限框架有SpringSecurity和Shiro(以前叫做jsecurity),對(duì)于SpringSecurity:功能太過(guò)強(qiáng)大以至于功能比較分散,使用起來(lái)也比較復(fù)雜,跟Spring結(jié)合的比較好。對(duì)于初學(xué)Spring Security者來(lái)說(shuō),曲線(xiàn)還是較大,需要深入學(xué)習(xí)其源碼和框架,配置起來(lái)也需要費(fèi)比較大的力氣,擴(kuò)展性也不是特別強(qiáng)。
對(duì)于新秀Shiro來(lái)說(shuō),好評(píng)還是比較多的,使用起來(lái)比較簡(jiǎn)單,功能也足夠強(qiáng)大,擴(kuò)展性也較好。聽(tīng)說(shuō)連Spring的官方都不用Spring Security,用的是Shiro,足見(jiàn)Shiro的優(yōu)秀。網(wǎng)上找到兩篇介紹:http://www.infoq.com/cn/articles/apache-shiro http://www.ibm.com/developerworks/cn/opensource/os-cn-shiro/,官網(wǎng)http://shiro.apache.org/ ,使用和配置起來(lái)還是比較簡(jiǎn)單。下面只是簡(jiǎn)單介紹下我們是如何配置和使用Shiro的(暫時(shí)只用到了Shiro的一部分,沒(méi)有配置shiro.ini文件)。
首先是添加過(guò)濾器,在web.xml中:
<filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> |
權(quán)限的認(rèn)證類(lèi):
public class ShiroDbRealm extends AuthorizingRealm { @Inject private UserService userService ;
/** * 認(rèn)證回調(diào)函數(shù),登錄時(shí)調(diào)用. */ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) UsernamePasswordToken token = (UsernamePasswordToken) authcToken; User user= userService.getUserByUserId(token.getUsername()); if (user!= null) { return new SimpleAuthenticationInfo(user.getUserId(), user.getUserId(), getName()); } else { return null; } } /** * 授權(quán)查詢(xún)回調(diào)函數(shù), 進(jìn)行鑒權(quán)但緩存中無(wú)用戶(hù)的授權(quán)信息時(shí)調(diào)用. */ protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String loginName = (String) principals.fromRealm(getName()).iterator().next(); User user= userService.getUserByUserId(loginName); if (user != null) { SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.addStringPermission("common-user"); return info; } else { return null; } } } |
Spring的配置文件:
<?xml version="1.0" encoding="UTF-8"?> <beans > <description>Shiro Configuration</description> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"/> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="shiroDbRealm" /> </bean> <bean id="shiroDbRealm" class="com.company.service.common.shiro.ShiroDbRealm" /> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"/> <property name="loginUrl" value="/common/security/login" /> <property name="successUrl" value="/common/security/welcome" /> <property name="unauthorizedUrl" value="/common/security/unauthorized"/> <property name="filterChainDefinitions"> <value> /resources/** = anon /manageUsers = perms[user:manage] /** = authc </value> </property> </bean> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /> <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> </beans> |
登錄的Controller:
@Controller @RequestMapping(value = "/common/security/*") public class SecurityController { @Inject private UserService userService; @RequestMapping(value = "/login") public String login(String loginName, String password, User user = userService.getUserByLogin(loginName); if (null != user) { setLogin(loginInfoVO.getUserId(), loginInfoVO.getUserId()); return "redirect:/common/security/welcome"; } else { return "redirect:/common/path?path=showLogin"; } }; public static final void setLogin(String userId, String password) { Subject currentUser = SecurityUtils.getSubject(); if (!currentUser.isAuthenticated()) { //collect user principals and credentials in a gui specific manner //such as username/password html form, X509 certificate, OpenID, etc. //We'll use the username/password example here since it is the most common. //(do you know what movie this is from? ;) UsernamePasswordToken token = new UsernamePasswordToken(userId, password); //this is all you have to do to support 'remember me' (no config - built in!): token.setRememberMe(true); currentUser.login(token); } };
@RequestMapping(value="/logout") @ResponseBody public void logout(HttpServletRequest request){ Subject subject = SecurityUtils.getSubject(); if (subject != null) { subject.logout(); } request.getSession().invalidate(); }; } |
注冊(cè)和獲取當(dāng)前登錄用戶(hù):
public static final void setCurrentUser(User user) { Subject currentUser = SecurityUtils.getSubject(); if (null != currentUser) { Session session = currentUser.getSession(); if (null != session) { session.setAttribute(Constants.CURRENT_USER, user); } } }; public static final User getCurrentUser() { Subject currentUser = SecurityUtils.getSubject(); if (null != currentUser) { Session session = currentUser.getSession(); if (null != session) { User user = (User) session.getAttribute(Constants.CURRENT_USER); if(null != user){ return user; } } } }; |
需要的jar包有3個(gè):shiro-core.jar,shiro-spring.jar,shiro-web.jar。感覺(jué)shiro用起來(lái)比SpringSecurity簡(jiǎn)單很多。
QQ:24889356