(一) 看到SpringSide4居然也用shiro作为安全框架,不是用的spring-security。着实有点惊讶。
apache-shiro的强大可见一斑。(二) apache-shiro依赖的包Xml代码
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.1</version>
</dependency>
除此之外还有一些东西也不可少spring, spring-mvc, ibatis等org.apache.shiro shiro-core 1.2.1 org.apache.shiro shiro-web 1.2.1 org.apache.shiro shiro-ehcache 1.2.1 org.apache.shiro shiro-spring 1.2.1
spring.3.1.2
spring-mvc.3.1.2
ibatis.2.3.4
cglib.2.2
Sql代码
-- -----------------------------------------------------
-- Table `shiro`.`TBL_PERMISSION`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `shiro`.`TBL_PERMISSION` ;
CREATE TABLE IF NOT EXISTS `shiro`.`TBL_PERMISSION` (
`PERMISSION_ID` INT NOT NULL AUTO_INCREMENT ,
`PERMISSION_NAME` VARCHAR(45) NULL ,
PRIMARY KEY (`PERMISSION_ID`) ,
UNIQUE INDEX `PERMISSION_NAME_UNIQUE` (`PERMISSION_NAME` ASC) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `shiro`.`TBL_ROLE`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `shiro`.`TBL_ROLE` ;
CREATE TABLE IF NOT EXISTS `shiro`.`TBL_ROLE` (
`ROLE_ID` INT NOT NULL AUTO_INCREMENT ,
`ROLE_NAME` VARCHAR(45) NULL ,
PRIMARY KEY (`ROLE_ID`) ,
UNIQUE INDEX `ROLE_NAME_UNIQUE` (`ROLE_NAME` ASC) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `shiro`.`TBL_USER`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `shiro`.`TBL_USER` ;
CREATE TABLE IF NOT EXISTS `shiro`.`TBL_USER` (
`USER_ID` INT NOT NULL AUTO_INCREMENT ,
`USER_USERNAME` VARCHAR(45) NOT NULL ,
`USER_PASSWORD` CHAR(32) NOT NULL ,
PRIMARY KEY (`USER_ID`) ,
UNIQUE INDEX `USER_USERNAME_UNIQUE` (`USER_USERNAME` ASC) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `shiro`.`TBL_PERMISSION_ROLE`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `shiro`.`TBL_PERMISSION_ROLE` ;
CREATE TABLE IF NOT EXISTS `shiro`.`TBL_PERMISSION_ROLE` (
`ROLE_ID` INT NOT NULL ,
`PERMISSION_ID` INT NOT NULL ,
PRIMARY KEY (`ROLE_ID`, `PERMISSION_ID`) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `shiro`.`TBL_ROLE_USER`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `shiro`.`TBL_ROLE_USER` ;
CREATE TABLE IF NOT EXISTS `shiro`.`TBL_ROLE_USER` (
`ROLE_ID` INT NOT NULL ,
`USER_ID` INT NOT NULL ,
PRIMARY KEY (`ROLE_ID`, `USER_ID`) )
ENGINE = InnoDB;
-- ------------------------------------------------------- Table `shiro`.`TBL_PERMISSION`-- -----------------------------------------------------DROP TABLE IF EXISTS `shiro`.`TBL_PERMISSION` ;CREATE TABLE IF NOT EXISTS `shiro`.`TBL_PERMISSION` ( `PERMISSION_ID` INT NOT NULL AUTO_INCREMENT , `PERMISSION_NAME` VARCHAR(45) NULL , PRIMARY KEY (`PERMISSION_ID`) , UNIQUE INDEX `PERMISSION_NAME_UNIQUE` (`PERMISSION_NAME` ASC) )ENGINE = InnoDB;-- ------------------------------------------------------- Table `shiro`.`TBL_ROLE`-- -----------------------------------------------------DROP TABLE IF EXISTS `shiro`.`TBL_ROLE` ;CREATE TABLE IF NOT EXISTS `shiro`.`TBL_ROLE` ( `ROLE_ID` INT NOT NULL AUTO_INCREMENT , `ROLE_NAME` VARCHAR(45) NULL , PRIMARY KEY (`ROLE_ID`) , UNIQUE INDEX `ROLE_NAME_UNIQUE` (`ROLE_NAME` ASC) )ENGINE = InnoDB;-- ------------------------------------------------------- Table `shiro`.`TBL_USER`-- -----------------------------------------------------DROP TABLE IF EXISTS `shiro`.`TBL_USER` ;CREATE TABLE IF NOT EXISTS `shiro`.`TBL_USER` ( `USER_ID` INT NOT NULL AUTO_INCREMENT , `USER_USERNAME` VARCHAR(45) NOT NULL , `USER_PASSWORD` CHAR(32) NOT NULL , PRIMARY KEY (`USER_ID`) , UNIQUE INDEX `USER_USERNAME_UNIQUE` (`USER_USERNAME` ASC) )ENGINE = InnoDB;-- ------------------------------------------------------- Table `shiro`.`TBL_PERMISSION_ROLE`-- -----------------------------------------------------DROP TABLE IF EXISTS `shiro`.`TBL_PERMISSION_ROLE` ;CREATE TABLE IF NOT EXISTS `shiro`.`TBL_PERMISSION_ROLE` ( `ROLE_ID` INT NOT NULL , `PERMISSION_ID` INT NOT NULL , PRIMARY KEY (`ROLE_ID`, `PERMISSION_ID`) )ENGINE = InnoDB;-- ------------------------------------------------------- Table `shiro`.`TBL_ROLE_USER`-- -----------------------------------------------------DROP TABLE IF EXISTS `shiro`.`TBL_ROLE_USER` ;CREATE TABLE IF NOT EXISTS `shiro`.`TBL_ROLE_USER` ( `ROLE_ID` INT NOT NULL , `USER_ID` INT NOT NULL , PRIMARY KEY (`ROLE_ID`, `USER_ID`) )ENGINE = InnoDB;自己实现一个UserDao, ibatis实现。这个不是本文要记述的重点,简单贴一下代码。
Xml代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="user">
<typeAlias alias="User" type="com.ztgame.sd.domain.User"/>
<resultMap class="User" id="result-map-01" groupBy="id">
<result property="id" column="USER_ID" />
<result property="username" column="USER_USERNAME" />
<result property="password" column="USER_PASSWORD" />
<result property="roleSet" resultMap="role.result-map-01" />
</resultMap>
<!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<sql id="select-base-01">
SELECT
u.USER_ID,
u.USER_USERNAME,
u.USER_PASSWORD,
r.ROLE_ID,
r.ROLE_NAME,
p.PERMISSION_ID,
p.PERMISSION_NAME
FROM
tbl_user as u,
tbl_role as r,
tbl_permission as p,
tbl_permission_role as pr,
tbl_role_user as ru
WHERE
u.USER_ID = ru.USER_ID
AND
r.ROLE_ID = ru.ROLE_ID
AND
p.PERMISSION_ID = pr.PERMISSION_ID
AND
r.ROLE_ID = pr.ROLE_ID
</sql>
<!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<select id="select-01" parameterClass="string" resultMap="result-map-01">
<include refid="select-base-01" />
AND
u.USER_USERNAME = #username#
</select>
</sqlMap>
SELECT u.USER_ID, u.USER_USERNAME, u.USER_PASSWORD, r.ROLE_ID, r.ROLE_NAME, p.PERMISSION_ID, p.PERMISSION_NAME FROM tbl_user as u, tbl_role as r, tbl_permission as p, tbl_permission_role as pr, tbl_role_user as ru WHERE u.USER_ID = ru.USER_ID AND r.ROLE_ID = ru.ROLE_ID AND p.PERMISSION_ID = pr.PERMISSION_ID AND r.ROLE_ID = pr.ROLE_ID
Java代码
public interface UserDao {
User findUserByUsername(String username);
}
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Resource
private SqlMapClientTemplate sqlMapClientTemplate;
@Override
public User findUserByUsername(String username) {
Validate.notEmpty(username, "用户名不可为null或empty string");
return (User) sqlMapClientTemplate.queryForObject("user.select-01", username);
}
}
public interface UserDao { User findUserByUsername(String username);}@Repository("userDao")public class UserDaoImpl implements UserDao { @Resource private SqlMapClientTemplate sqlMapClientTemplate; @Override public User findUserByUsername(String username) { Validate.notEmpty(username, "用户名不可为null或empty string"); return (User) sqlMapClientTemplate.queryForObject("user.select-01", username); }}(三) 用户和权限数据源是自己设计的,应该实现自己的Realm对象。
Java代码
package com.ztgame.sd.security.realm;
import java.util.HashSet;
import java.util.Set;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import com.ztgame.sd.dao.UserDao;
import com.ztgame.sd.domain.Permission;
import com.ztgame.sd.domain.Role;
import com.ztgame.sd.domain.User;
public class JdbcRealm extends AuthorizingRealm
implements
Realm,
InitializingBean
{
private UserDao userDao;
// ------------------------------------------------------------------------------------------------------------
@Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(userDao);
}
// ------------------------------------------------------------------------------------------------------------
@Override
public String getName() {
return getClass().getName();
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String username = (String) super.getAvailablePrincipal(principals);
User user = userDao.findUserByUsername(username);
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
Set<String> roles = new HashSet<String>();
Set<String> permissions = new HashSet<String>();
for (Role role : user.getRoleSet()) {
roles.add(role.getName());
for (Permission per : role.getPermissionSet()) {
permissions.add(per.getName());
}
}
info.addRoles(roles);
info.addStringPermissions(permissions);
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
SimpleAuthenticationInfo info = null;
UsernamePasswordToken upt = (UsernamePasswordToken) token;
String username = upt.getUsername();
User user = userDao.findUserByUsername(username);
if (user == null) {
throw new AuthenticationException();
}
info = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());
return info;
}
// ------------------------------------------------------------------------------------------------------------
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
package com.ztgame.sd.security.realm;import java.util.HashSet;import java.util.Set;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.SimpleAuthenticationInfo;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.authz.SimpleAuthorizationInfo;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.realm.Realm;import org.apache.shiro.subject.PrincipalCollection;import org.springframework.beans.factory.InitializingBean;import org.springframework.util.Assert;import com.ztgame.sd.dao.UserDao;import com.ztgame.sd.domain.Permission;import com.ztgame.sd.domain.Role;import com.ztgame.sd.domain.User;public class JdbcRealm extends AuthorizingRealm implements Realm, InitializingBean{ private UserDao userDao; // ------------------------------------------------------------------------------------------------------------ @Override public void afterPropertiesSet() throws Exception { Assert.notNull(userDao); } // ------------------------------------------------------------------------------------------------------------ @Override public String getName() { return getClass().getName(); } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String username = (String) super.getAvailablePrincipal(principals); User user = userDao.findUserByUsername(username); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); Set(四) apache-shiro的配置web.xmlroles = new HashSet (); Set permissions = new HashSet (); for (Role role : user.getRoleSet()) { roles.add(role.getName()); for (Permission per : role.getPermissionSet()) { permissions.add(per.getName()); } } info.addRoles(roles); info.addStringPermissions(permissions); return info; } @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { SimpleAuthenticationInfo info = null; UsernamePasswordToken upt = (UsernamePasswordToken) token; String username = upt.getUsername(); User user = userDao.findUserByUsername(username); if (user == null) { throw new AuthenticationException(); } info = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName()); return info; } // ------------------------------------------------------------------------------------------------------------ public void setUserDao(UserDao userDao) { this.userDao = userDao; }}
Xml代码
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<!-- apache-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>
<!-- 其他无关apache-shiro -->
</web-app>
spring-shiro.xmlshiroFilter org.springframework.web.filter.DelegatingFilterProxy shiroFilter /*
Xml代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c" xmlns:util="http://www.springframework.org/schema/util"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login" />
<property name="successUrl" value="/login/loginSuccessFull" />
<property name="unauthorizedUrl" value="/login/unauthorized" />
<!--
<property name="filterChainDefinitions">
<value>
/ = anon
</value>
</property>
-->
</bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="authenticator" ref="authenticator" />
<property name="sessionManager" ref="sessionManager" />
<property name="cacheManager" ref="cacheManager" />
<property name="realms">
<list>
<bean class="com.ztgame.sd.security.realm.JdbcRealm">
<property name="userDao" ref="userDao" />
<property name="credentialsMatcher" ref="hashedCredentialsMatcher" />
</bean>
</list>
</property>
</bean>
<bean id="authenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator" />
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<property name="sessionDAO" ref="sessionDAO" />
</bean>
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager" />
<bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.MemorySessionDAO" />
<bean id="hashedCredentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="MD5" />
<property name="storedCredentialsHexEncoded" value="true" />
<property name="hashIterations" value="1" />
</bean>
</beans>
spring-mvc.xml
Xml代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c" xmlns:util="http://www.springframework.org/schema/util"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
<!-- 其他spring-mvc框架配置 -->
<!--
以下两个bean的配置是为了在Controller层使用元注释控制权限
如果使用spring-mvc一定要不要放在webroot的配置文件中
-->
<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>
(五) jsp-taglib 支持
<shiro:authenticated> 登录之后
<shiro:notAuthenticated> 不在登录状态时
<shiro:guest> 用户在没有RememberMe时
<shiro:user> 用户在RememberMe时
<shiro:hasAnyRoles name="abc,123" > 在有abc或者123角色时
<shiro:hasRole name="abc"> 拥有角色abc
<shiro:lacksRole name="abc"> 没有角色abc
<shiro:hasPermission name="abc"> 拥有权限abc
<shiro:lacksPermission name="abc"> 没有权限abc
<shiro:principal> 显示用户登录名
anon -- org.apache.shiro.web.filter.authc.AnonymousFilter
authc -- org.apache.shiro.web.filter.authc.FormAuthenticationFilter
authcBasic -- org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
perms -- org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
port -- org.apache.shiro.web.filter.authz.PortFilter
rest -- org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
roles -- org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
ssl -- org.apache.shiro.web.filter.authz.SslFilter
user -- org.apache.shiro.web.filter.authc.UserFilter
logout -- org.apache.shiro.web.filter.authc.LogoutFilter
@RequiresAuthentication 验证用户是否登录,等同于方法subject.isAuthenticated() 结果为true时
@RequiresUser 验证用户是否被记忆,user有两种含义:一种是成功登录的(subject.isAuthenticated()结果为true)另外一种是被记忆的(subject.isRemembered()结果为true)
@RequiresGuest 验证是否为匿名请求
@RequiresRoles 必须要有角色
@RequiresPermissions 必须要有权限
下载
(48.3 KB)
(7.8 KB)
(880 Bytes)