一、数据库表有5个:users、roles、perms、users_roles、roles_perms。
大家一看就知道这5个表是做什么用的了。
脚本如下:
- /*
- 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、Perm。
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<Role> roles = new HashSet<Role>();
- @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<Role> getRoles() {
- return roles;
- }
- public void setRoles(Set<Role> 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<User> users = new HashSet<User>();
- private Set<Perm> perms = new HashSet<Perm>();
- @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<User> getUsers() {
- return users;
- }
- public void setUsers(Set<User> 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<Perm> getPerms() {
- return perms;
- }
- public void setPerms(Set<Perm> 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<Role> roles = new HashSet<Role>();
- @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<Role> getRoles() {
- return roles;
- }
- public void setRoles(Set<Role> roles) {
- this.roles = roles;
- }
- }
三、域对象的DAO类:UserDAO、RoleDAO、PermDAO,为方便session的获取,他们都继承自BaseDAO,该类代码如下:
- 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<String> 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<String> loadUserAuthoritiesByName(String username) {
- User user = this.getUserByName(username);
- if (user != null) {
- Set<Role> roles = user.getRoles();
- List<String> auth = new ArrayList<String>();
- Iterator<Role> 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<Perm> 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<Perm> findPermByUri(String requestUri) {
- Session s = getSession();
- Query query = s.createQuery("from Perm");
- List<Perm> permlist = query.list();
- List<Perm> perms = new ArrayList<Perm>();
- 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页面的配置:
web.xml代码如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <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>mis2013</display-name>
- <welcome-file-list>
- <welcome-file>index.html</welcome-file>
- <welcome-file>index.htm</welcome-file>
- <welcome-file>index.jsp</welcome-file>
- <welcome-file>default.html</welcome-file>
- <welcome-file>default.htm</welcome-file>
- <welcome-file>default.jsp</welcome-file>
- </welcome-file-list>
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath:Context.xml,classpath:Security.xml</param-value>
- </context-param>
- <!-- 配置spiring security -->
- <filter>
- <filter-name>springSecurityFilterChain</filter-name>
- <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>springSecurityFilterChain</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- <!-- 配置spiring security结束 -->
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
- <filter>
- <filter-name>struts2</filter-name>
- <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>struts2</filter-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"%>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <title>用户登陆</title>
- </head>
- <body>
- <a href="<s:url value='/index.jsp'/>">首页</a>
- <a href="<s:url value='/register.jsp'/>">注册</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代码如下:
- <?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: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">true</prop>
- <prop key="hibernate.dialect">
- org.hibernate.dialect.MySQLDialect
- </prop>
- <prop key="hibernate.hbm2ddl.auto">update</prop>
- </props>
- </property>
- <property name="annotatedClasses">
- <list>
- <value>pw.cmos.user.model.User</value>
- <value>pw.cmos.user.model.Role</value>
- <value>pw.cmos.user.model.Perm</value>
- </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了。
五、重头戏,Security.xml的配置和自定义类的实现。
- <?xml version="1.0" encoding="UTF-8"?>
- <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过滤器链中插入一个自定义的过滤器。如<custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR" />,该过滤器需要三个参数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<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
- User user = new User();
- try {
- user = userDao.getUserByName(username);
- List<String> 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<ConfigAttribute> configAttributes)
- throws AccessDeniedException, InsufficientAuthenticationException {
- if (configAttributes == null) {
- return;
- }
- Iterator<ConfigAttribute> 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<ConfigAttribute> 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<ConfigAttribute> result = new ArrayList<ConfigAttribute>();
- ConfigAttribute attribute = new SecurityConfig("ROLE_BASE");
- result.add(attribute);
- try {
- List<Perm> permList = permDao.findPermByUri(url);
- if (permList != null && permList.size() > 0) {
- for (Perm perm : permList) {
- Set<Role> 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<ConfigAttribute> 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数组,以此返回给系统进行授权。
相关推荐
在本文中,我们将深入探讨如何在Spring Security 3.1版本中实现验证码的自定义登录,以增强系统安全性,防止恶意自动登录攻击。 首先,验证码是Web应用中防止自动化脚本或机器人恶意操作的一种常见手段。在登录过程...
在3.1版本中,它提供了丰富的功能来管理应用程序的安全性,包括URL访问控制、用户认证、授权以及方法级别的安全拦截。下面将详细探讨Spring Security 3.1中的配置实例。 ### 1. URL 和方法拦截 Spring Security...
在这个基于Spring Security 3.1的示例项目中,我们将深入探讨这个版本的核心概念和功能,以及如何在一个简单的应用程序中实现它们。 1. **核心组件与架构** Spring Security 3.1 的核心组件包括:过滤器链、访问...
1. **简单示例**:此示例完全基于配置文件的方式实现,具体细节未在文档中详细展开,但可以理解为一个快速入门的例子,用于展示 Spring Security 基础配置的方法。 2. **复杂示例**:这个示例结合了第二种和第三种...
本示例是基于Spring Security 3.1版本的一个入门级演示项目,旨在帮助开发者快速理解并开始使用该框架。 在Spring Security 3.1中,主要涉及的核心概念有以下几点: 1. **安全过滤器链**:Spring Security通过一...
结合Spring MVC和Spring Security,我们可以通过注解的方式轻松实现用户登录、权限验证等功能。例如,可以创建一个过滤器链,使用Spring Security的DelegatingFilterProxy来启动SecurityContextFilter,处理用户的...
这个"spring-security-3.1.x.zip"压缩包包含的是Spring Security 3.1版本的源代码,这对于开发者深入理解其工作原理、自定义功能或者排查问题非常有帮助。下面将详细探讨Spring Security的核心概念、主要组件以及3.1...
**Spring Security**是一种广泛应用于Java企业级项目中的安全框架,它基于Spring AOP(面向切面编程)和Servlet过滤器来提供全面的安全解决方案。该框架能够在Web请求级别以及方法调用级别处理身份验证...
文档中详细阐述了Spring Security的基本架构,包括核心类、配置元素以及如何实现身份验证和授权的流程。对于初学者来说,这是了解Spring Security工作原理和开始项目开发的好资料。 《spring-security3.0.rar》是一...
在本项目中,我们主要探讨的是如何利用Spring Boot、Spring Security、JWT(JSON Web Tokens)、MyBatis-Plus以及MySQL数据库来构建一个完整的权限管理系统。下面将详细解析这些技术及其在项目中的应用。 1. Spring...
例如,你可以研究如何自定义认证和授权逻辑,如何集成自定义的用户存储,或者如何实现OAuth2的扩展功能,如刷新令牌的生命周期管理。同时,源码阅读还能帮助理解Spring Security和OAuth2的安全机制,以及它们如何...
Spring Security 提供了一套完整的解决方案来解决Web应用程序和普通Java应用程序中的安全问题,包括认证(Authentication)、授权(Authorization)以及安全配置等。 **1.2. 历史** Spring Security 的前身是Acegi...
在SpringSecurity 3.1版本中,相比3.0版本,配置上有一些变化,但其核心仍然是通过一系列过滤器来实现安全控制。本文将详细介绍SpringSecurity的体系结构、配置以及在非数据库环境下进行安全保护的基本步骤。 1. **...
- 讨论如何通过自定义的方式,替代Spring Security中原有的资源管理功能。 **6. 控制用户信息** - **6.1 MD5加密** - 讲解MD5加密算法在用户密码保护中的应用。 - **6.2 盐值加密** - 介绍盐值加密的概念及其在...
Spring Security 提供了多种方式来进行用户身份验证,包括内存中的用户列表、数据库查询等方式。 ###### 2.3.7 多个 HttpSecurity 对于复杂的应用场景,可能需要配置多个 `HttpSecurity` 实例来分别处理不同的安全...
- **定义:** Spring Security 是一个强大的且高度可定制的身份验证和授权框架。它为基于 Java 的企业级应用程序提供了功能丰富的 API 来满足安全需求。 - **特点:** 易于集成到现有应用程序中,并且能够通过自定义...
Spring Security 3.0.1是该框架的一个版本,提供了全面的安全控制,包括身份验证、授权、会话管理以及防止各种网络攻击。本文档将深入探讨Spring Security 3.0.1的核心概念、配置和使用方法。 1. **核心概念** - ...