一、数据库表有5个:users、roles、perms、users_roles、roles_perms。
/*
Navicat MySQL Data Transfer
Source Server : localhost_3306
Source Server Version : 50154
Source Host : localhost:3306
Source Database : mis2013
Target Server Type : MYSQL
Target Server Version : 50154
File Encoding : 65001
Date: 2013-07-10 01:08:05
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `perms`
-- ----------------------------
DROP TABLE IF EXISTS `perms`;
CREATE TABLE `perms` (
`id` varchar(36) NOT NULL,
`permname` varchar(50) NOT NULL,
`permtype` varchar(15) DEFAULT 'jsp',
`permstr` varchar(255) DEFAULT NULL,
`priority` int(11) DEFAULT '0',
`description` varchar(255) DEFAULT '鏃?,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of perms
-- ----------------------------
INSERT INTO `perms` VALUES ('perm1', '绠$悊鐩綍', 'dir', '/adroot/**', '1', '鏃?);
INSERT INTO `perms` VALUES ('perm2', '鐧诲綍椤甸潰', 'jsp', '/login.jsp', '0', '鏃?);
INSERT INTO `perms` VALUES ('perm3', '娉ㄥ唽椤甸潰', 'jsp', '/register.jsp', '0', '鏃?);
INSERT INTO `perms` VALUES ('perm4', '绯荤粺涓婚〉', 'jsp', '/index.jsp', '0', '鏃?);
-- ----------------------------
-- Table structure for `roles`
-- ----------------------------
DROP TABLE IF EXISTS `roles`;
CREATE TABLE `roles` (
`id` varchar(36) NOT NULL,
`description` varchar(255) DEFAULT NULL,
`rolename` varchar(50) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of roles
-- ----------------------------
INSERT INTO `roles` VALUES ('ROLE_ADMIN', '绠$悊瑙掕壊', 'ROLE_ADMIN');
INSERT INTO `roles` VALUES ('ROLE_ANONYMOUS', '璁垮瑙掕壊', 'ROLE_ANONYMOUS');
INSERT INTO `roles` VALUES ('ROLE_USER', '鐢ㄦ埛瑙掕壊', 'ROLE_USER');
-- ----------------------------
-- Table structure for `roles_perms`
-- ----------------------------
DROP TABLE IF EXISTS `roles_perms`;
CREATE TABLE `roles_perms` (
`roles_id` varchar(36) NOT NULL,
`perms_id` varchar(36) NOT NULL,
PRIMARY KEY (`roles_id`,`perms_id`),
KEY `FK2E481B81CADB7376` (`perms_id`),
KEY `FK2E481B81A0EF5B82` (`roles_id`),
CONSTRAINT `FK2E481B81A0EF5B82` FOREIGN KEY (`roles_id`) REFERENCES `roles` (`id`),
CONSTRAINT `FK2E481B81CADB7376` FOREIGN KEY (`perms_id`) REFERENCES `perms` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of roles_perms
-- ----------------------------
INSERT INTO `roles_perms` VALUES ('ROLE_ADMIN', 'perm1');
INSERT INTO `roles_perms` VALUES ('ROLE_ANONYMOUS', 'perm2');
INSERT INTO `roles_perms` VALUES ('ROLE_USER', 'perm2');
INSERT INTO `roles_perms` VALUES ('ROLE_ANONYMOUS', 'perm3');
INSERT INTO `roles_perms` VALUES ('ROLE_USER', 'perm3');
INSERT INTO `roles_perms` VALUES ('ROLE_USER', 'perm4');
-- ----------------------------
-- Table structure for `users`
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` varchar(36) NOT NULL,
`username` varchar(50) NOT NULL,
`password` varchar(32) DEFAULT NULL,
`enabled` tinyint(4) DEFAULT '1',
`description` varchar(255) DEFAULT '鏃?,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of users
-- ----------------------------
INSERT INTO `users` VALUES ('admin', 'admin', 'admin', '1', null);
INSERT INTO `users` VALUES ('user', 'user', 'user', '1', null);
-- ----------------------------
-- Table structure for `users_roles`
-- ----------------------------
DROP TABLE IF EXISTS `users_roles`;
CREATE TABLE `users_roles` (
`users_id` varchar(36) NOT NULL,
`roles_id` varchar(36) NOT NULL,
PRIMARY KEY (`users_id`,`roles_id`),
KEY `FKF6CCD9C6A0EF5B82` (`roles_id`),
KEY `FKF6CCD9C6A0F27FAC` (`users_id`),
CONSTRAINT `FKF6CCD9C6A0EF5B82` FOREIGN KEY (`roles_id`) REFERENCES `roles` (`id`),
CONSTRAINT `FKF6CCD9C6A0F27FAC` FOREIGN KEY (`users_id`) REFERENCES `users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of users_roles
-- ----------------------------
INSERT INTO `users_roles` VALUES ('admin', 'ROLE_ADMIN');
INSERT INTO `users_roles` VALUES ('admin', 'ROLE_ANONYMOUS');
INSERT INTO `users_roles` VALUES ('user', 'ROLE_ANONYMOUS');
INSERT INTO `users_roles` VALUES ('admin', 'ROLE_USER');
INSERT INTO `users_roles` VALUES ('user', 'ROLE_USER');
User
和Role
、Role
和Perm
都是多对多的关系。代码如下:
package pw.cmos.user.model;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Proxy;
@Entity
@Proxy(lazy = false)
@Table(name = "users", catalog = "mis2013")
public class User {
private String id;
private String username;
private String password;
private boolean enabled;
private String description;
private Set roles = new HashSet();
@GenericGenerator(name = "generator", strategy = "uuid.hex")
@Id
@GeneratedValue(generator = "generator")
@Column(name = "id", unique = true, nullable = false, length = 36)
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Column(name = "username", nullable = false, length = 50)
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Column(name = "password", length = 32)
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Column(name = "enabled")
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Column(name = "description", length = 255)
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@ManyToMany(targetEntity = Role.class, fetch = FetchType.EAGER)
@JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "users_id"), inverseJoinColumns = @JoinColumn(name = "roles_id"))
public Set getRoles() {
return roles;
}
public void setRoles(Set roles) {
this.roles = roles;
}
}
package pw.cmos.user.model;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name = "roles", catalog = "mis2013")
public class Role {
private String id;
private String rolename;
private String description;
private Set users = new HashSet();
private Set perms = new HashSet();
@GenericGenerator(name = "generator", strategy = "uuid.hex")
@Id
@GeneratedValue(generator = "generator")
@Column(name = "id", unique = true, nullable = false, length = 36)
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Column(name = "rolename", nullable = false, length = 50)
public String getRolename() {
return rolename;
}
public void setRolename(String rolename) {
this.rolename = rolename;
}
@Column(name = "description", length = 255)
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@ManyToMany(mappedBy = "roles")
public Set getUsers() {
return users;
}
public void setUsers(Set users) {
this.users = users;
}
@ManyToMany(targetEntity = Perm.class, fetch = FetchType.EAGER)
@JoinTable(name = "roles_perms", joinColumns = @JoinColumn(name = "roles_id"), inverseJoinColumns = @JoinColumn(name = "perms_id"))
public Set getPerms() {
return perms;
}
public void setPerms(Set perms) {
this.perms = perms;
}
}
package pw.cmos.user.model;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name = "perms", catalog = "mis2013")
public class Perm {
private String id;
private String permname;
private String permtype;
private String permstr;
private Integer priority;
private String description;
private Set roles = new HashSet();
@Id
@GeneratedValue(generator = "generator")
@GenericGenerator(name = "generator", strategy = "uuid.hex")
@Column(name = "id", unique = true, nullable = false, length = 36)
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Column(name = "permname", nullable = false, length = 50)
public String getPermname() {
return permname;
}
public void setPermname(String permname) {
this.permname = permname;
}
@Column(name = "permtype", length = 15)
public String getPermtype() {
return permtype;
}
public void setPermtype(String permtype) {
this.permtype = permtype;
}
@Column(name = "permstr", length = 255)
public String getPermstr() {
return permstr;
}
public void setPermstr(String permstr) {
this.permstr = permstr;
}
@Column(name = "priority")
public Integer getPriority() {
return priority;
}
public void setPriority(Integer priority) {
this.priority = priority;
}
@Column(name = "description", length = 255)
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@ManyToMany(mappedBy = "perms", targetEntity = Role.class, fetch = FetchType.EAGER)
public Set getRoles() {
return roles;
}
public void setRoles(Set roles) {
this.roles = roles;
}
}
package pw.cmos.user.dao;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
public class BaseDAO {
@Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public Session getSession() {
return sessionFactory.getCurrentSession();
}
}
这里通过注解方式注入sessionFactory
,该工厂类在xml中已经配置,请参看后面的Context.xml代码。
为了减少类之间的耦合,一般考虑用接口来实现类与类的调用。DAO都实现了相应的接口,比如UserDAO类实现IUserDAO接口。
package pw.cmos.user.dao;
import java.util.List;
import pw.cmos.user.model.User;
public interface IUserDAO {
public abstract void save(User user);
public abstract void delete(User user);
public abstract User findUserById(final String id);
public abstract User findUserByUsername(final String username);
public abstract List findByProperty(String propertyName, Object value);
public abstract User getUserByName(String username);
public abstract List loadUserAuthoritiesByName(String username);
}
package pw.cmos.user.dao;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.stereotype.Repository;
import pw.cmos.user.model.Role;
import pw.cmos.user.model.User;
@Repository
public class UserDAO extends BaseDAO implements IUserDAO {
@Override
public void save(User user) {
}
@Override
public void delete(User user) {
// TODO Auto-generated method stub
}
@Override
public User findUserById(String id) {
// TODO Auto-generated method stub
return null;
}
@Override
public User findUserByUsername(String username) {
// TODO Auto-generated method stub
return null;
}
@Override
public List findByProperty(String propertyName, Object value) {
// TODO Auto-generated method stub
return null;
}
public User getUserByName(String username) {
Session s = getSession();
Query query = s.createQuery("from User as u where u.username = ?");
query.setString(0, username);
User user = (User) query.uniqueResult();
return user;
}
public List loadUserAuthoritiesByName(String username) {
User user = this.getUserByName(username);
if (user != null) {
Set roles = user.getRoles();
List auth = new ArrayList();
Iterator it = roles.iterator();
while (it.hasNext()) {
auth.add(((Role) it.next()).getRolename());
}
return auth;
} else {
return null;
}
}
}
因只谈谈spring security 的自定义实现,所以DAO类其它方法都没有具体去实现,这里仅用到两个方法:getUserByName和loadUserAuthoritiesByName。这两个方法在后面的认证中需要用到,他们主要用于根据用户名来获得认证所需的角色名,返回角色名的字符串数组。
package pw.cmos.user.dao;
import java.util.List;
import pw.cmos.user.model.Perm;
public interface IPermDAO {
public abstract void save(Perm perm);
public abstract void delete(Perm perm);
public abstract Perm findPermById(final String id);
public abstract Perm findPermByPermname(final String permname);
public abstract List findPermByUri(final String requestUri);
public abstract List findByProperty(String propertyName, Object value);
}
package pw.cmos.user.dao;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.springframework.stereotype.Repository;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import pw.cmos.user.model.Perm;
@Repository
public class PermDAO extends BaseDAO implements IPermDAO {
@Override
public void save(Perm perm) {
// TODO Auto-generated method stub
}
@Override
public void delete(Perm perm) {
// TODO Auto-generated method stub
}
@Override
public Perm findPermById(String id) {
// TODO Auto-generated method stub
return null;
}
@Override
public Perm findPermByPermname(String permname) {
// TODO Auto-generated method stub
return null;
}
@Override
public List findPermByUri(String requestUri) {
Session s = getSession();
Query query = s.createQuery("from Perm");
List permlist = query.list();
List perms = new ArrayList();
for (Perm perm : permlist) {
if (urlMatcher(perm.getPermstr(), requestUri))
perms.add(perm);
}
return perms;
}
private boolean urlMatcher(String permstr, String requestUri) {
boolean isMatcher = false;
PathMatcher matcher = new AntPathMatcher();
isMatcher = matcher.match(permstr, requestUri);
return isMatcher;
}
@Override
public List findByProperty(String propertyName, Object value) {
// TODO Auto-generated method stub
return null;
}
}
PermDAO也仅实现了findPermByUri方法,这个方法在后面的授权中需要用到,主要用于根据用户请求的url资源地址与perm表中的授权掩码匹配,匹配通过的perm将以数组方式返回。
web.xml代码如下:
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>mis2013display-name>
<welcome-file-list>
<welcome-file>index.htmlwelcome-file>
<welcome-file>index.htmwelcome-file>
<welcome-file>index.jspwelcome-file>
<welcome-file>default.htmlwelcome-file>
<welcome-file>default.htmwelcome-file>
<welcome-file>default.jspwelcome-file>
welcome-file-list>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:Context.xml,classpath:Security.xmlparam-value>
context-param>
<filter>
<filter-name>springSecurityFilterChainfilter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxyfilter-class>
filter>
<filter-mapping>
<filter-name>springSecurityFilterChainfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
<filter>
<filter-name>struts2filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilterfilter-class>
filter>
<filter-mapping>
<filter-name>struts2filter-name>
<url-pattern>/*url-pattern>
filter-mapping>
web-app>
login.jsp代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<%@ taglib prefix="sec"
uri="http://www.springframework.org/security/tags"%>
<html>
<head>
<title>用户登陆title>
head>
<body>
<a href=" ">首页a>
<a href=" ">注册a>
<hr size="1" />
<s:form action="/j_spring_security_check" method="POST" namespace="/user">
<s:fielderror>s:fielderror>
<s:textfield key="用户" name="j_username">s:textfield>
<s:password key="密码" name="j_password" style="width:155px;">s:password>
<s:submit value="登陆系统">s:submit>
<s:actionerror />
s:form>
body>
html>
action必须使用/j_spring_security_check,表单name相应为:j_username,j_password。如果退出登录action为:/j_spring_security_logout
Comtext.xml代码如下:
<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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-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
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd ">
<context:component-scan base-package="pw.cmos" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mis2013">
property>
<property name="username" value="root">property>
<property name="password" value="******">property>
bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">trueprop>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
prop>
<prop key="hibernate.hbm2ddl.auto">updateprop>
props>
property>
<property name="annotatedClasses">
<list>
<value>pw.cmos.user.model.Uservalue>
<value>pw.cmos.user.model.Rolevalue>
<value>pw.cmos.user.model.Permvalue>
list>
property>
bean>
<tx:annotation-driven transaction-manager="txManager" />
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
bean>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="create*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="*" read-only="true" />
tx:attributes>
tx:advice>
<aop:config proxy-target-class="true">
<aop:pointcut id="dao" expression="execution(* pw.cmos..dao.*.*(..))" />
<aop:advisor pointcut-ref="dao" advice-ref="txAdvice" />
aop:config>
beans>
这里配置了事务,因为我们在获取session时使用的是sessionFactory.getCurrentSession(),如果不配置事务的话,session是获取不到的。配置事务主要是对dao包下面的DAO方法都使用事务,这样就不需要我们在每个方法中显式使用事务api了。
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<http pattern="/login.jsp" security="none" />
<http pattern="/accessDenied.jsp" security="none" />
<http auto-config="true">
<form-login login-page="/login.jsp"
authentication-failure-url="/login.jsp" />
<custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR" />
http>
<beans:bean id="myFilter"
class="pw.cmos.web.security.MyFilterSecurityInterceptor">
<beans:property name="accessDecisionManager" ref="myAccessDecisionManager" />
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="securityMetadataSource" ref="mySecurityMetadataSource" />
beans:bean>
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="myUserDetailsService">
authentication-provider>
authentication-manager>
<beans:bean name="myUserDetailsService" class="pw.cmos.web.security.MyUserDetailsService">
beans:bean>
<beans:bean name="myAccessDecisionManager"
class="pw.cmos.web.security.MyAccessDecisionManager">
beans:bean>
<beans:bean name="mySecurityMetadataSource"
class="pw.cmos.web.security.MyInvocationSecurityMetadataSourceService">
beans:bean>
beans:beans>
这里,我们要自定义的话,只能在spring security过滤器链中插入一个自定义的过滤器。如,该过滤器需要三个参数accessDecisionManager、authenticationManager、securityMetadataSource。代码如下:
package pw.cmos.web.security;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
import org.springframework.security.access.intercept.InterceptorStatusToken;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor
implements Filter {
private FilterInvocationSecurityMetadataSource securityMetadataSource;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
FilterInvocation fi = new FilterInvocation(request, response, chain);
invoke(fi);
}
@Override
public void destroy() {
}
@Override
public Class> getSecureObjectClass() {
return FilterInvocation.class;
}
@Override
public SecurityMetadataSource obtainSecurityMetadataSource() {
return this.securityMetadataSource;
}
public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
return this.securityMetadataSource;
}
public void invoke(FilterInvocation fi) throws IOException,
ServletException {
InterceptorStatusToken token = super.beforeInvocation(fi);
try {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} finally {
super.afterInvocation(token, null);
}
}
public void setSecurityMetadataSource(
FilterInvocationSecurityMetadataSource securityMetadataSource) {
this.securityMetadataSource = securityMetadataSource;
}
}
authenticationManager类我们主要是关心它的authentication-provider,这里我们用UserDetailsService的实现类做provider,自定义了UserDetailsService的实现,代码如下:
package pw.cmos.web.security;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import pw.cmos.user.dao.IUserDAO;
import pw.cmos.user.dao.UserDAO;
import pw.cmos.user.model.User;
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private IUserDAO userDao;
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
Collection auths = new ArrayList();
User user = new User();
try {
user = userDao.getUserByName(username);
List authStr = userDao.loadUserAuthoritiesByName(username);
for (String authName : authStr) {
SimpleGrantedAuthority authority = new SimpleGrantedAuthority(
authName);
auths.add(authority);
}
} catch (Exception e) {
e.printStackTrace();
}
return new org.springframework.security.core.userdetails.User(
user.getUsername(), user.getPassword(), true, true, true, true,
auths);
}
}
package pw.cmos.web.security;
import java.util.Collection;
import java.util.Iterator;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
public class MyAccessDecisionManager implements AccessDecisionManager {
@Override
public void decide(Authentication authentication, Object object,
Collection configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException {
if (configAttributes == null) {
return;
}
Iterator ite = configAttributes.iterator();
while (ite.hasNext()) {
ConfigAttribute ca = ite.next();
String needRole = ((SecurityConfig) ca).getAttribute();
for (GrantedAuthority ga : authentication.getAuthorities()) {
if (needRole.trim().equals(ga.getAuthority().trim())) {
return;
}
}
}
throw new AccessDeniedException("无权限!");
}
@Override
public boolean supports(ConfigAttribute attribute) {
return true;
}
@Override
public boolean supports(Class> clazz) {
return true;
}
}
package pw.cmos.web.security;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.FilterInvocation;
import pw.cmos.user.dao.IPermDAO;
import pw.cmos.user.dao.PermDAO;
import pw.cmos.user.model.Perm;
import pw.cmos.user.model.Role;
public class MyInvocationSecurityMetadataSourceService implements
FilterInvocationSecurityMetadataSource {
@Autowired
private IPermDAO permDao;
@Override
public Collection getAttributes(Object object)
throws IllegalArgumentException {
String url = ((FilterInvocation) object).getRequestUrl();
int firstQuestionMarkIndex = url.indexOf("?");
if (firstQuestionMarkIndex != -1) {
url = url.substring(0, firstQuestionMarkIndex);
}
System.out.println("url:" + url);
List result = new ArrayList();
ConfigAttribute attribute = new SecurityConfig("ROLE_BASE");
result.add(attribute);
try {
List permList = permDao.findPermByUri(url);
if (permList != null && permList.size() > 0) {
for (Perm perm : permList) {
Set roles = perm.getRoles();
if (roles != null && roles.size() > 0) {
for (Role role : roles) {
ConfigAttribute conf = new SecurityConfig(
role.getRolename());
result.add(conf);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
@Override
public Collection getAllConfigAttributes() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean supports(Class> clazz) {
// TODO Auto-generated method stub
return true;
}
}
getAttributes的功能:对请求url进行简单处理后,然后与perm表中的授权掩码匹配,查找出匹配的角色,然后以角色名new出的SecurityConfig数组,以此返回给系统进行授权。