Spring Security例子
Spring security 简单例子
使用xml方式
pom.xml引入依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.spsecurity.xml</groupId>
<artifactId>spsecurity-xml</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>spsecurity-xml Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<spring.version>3.2.8.RELEASE</spring.version>
<spring.security.version>3.2.3.RELEASE</spring.security.version>
</properties>
<dependencies>
<!-- spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>
<!-- servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
<build>
<finalName>spsecurity-xml</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
web.xml 配置
<web-app id="webId" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>Archetype Created Web Application</display-name>
<!-- 加载spring容器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-security.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<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>
<!-- springmvc前端控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- post乱码过虑器 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
spring配置
spring-mvc.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 扫描controller的包 -->
<context:component-scan base-package="com.spsecurity.xml.controller" />
<!-- 配置JSP视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
</bean>
</beans>
spring-security.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:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/login" access="permitAll()" />
<security:intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<!-- <security:http auto-config="true" use-expressions="false">
<security:intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<security:intercept-url pattern="/**" access="ROLE_USER" /> -->
<security:form-login login-page="/login"
default-target-url="/index"
authentication-failure-url="/login?error"
username-parameter="username" password-parameter="password" />
<security:logout logout-success-url="/login?logout" />
</security:http>
<security:authentication-manager>
<security:authentication-provider >
<security:user-service>
<security:user name="user" password="user" authorities="ROLE_USER" />
<security:user name="admin" password="admin" authorities="ROLE_USER, ROLE_ADMIN" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
自定义jsp页面
登录login.sjp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<span id="msg"></span>
<form action="<%=request.getContextPath()%>/j_spring_security_check" method="post">
登录名:<input name="username" /> <br />
密码:<input name="password" type="password" /><br>
<input type="submit" value="登录" />
</form>
<script type="text/javascript">
var msg = "<%=request.getAttribute("msg")%>";
document.getElementById("msg").innerHTML = msg;
</script>
</body>
</html>
首页
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
首页
<br /> ....
<br />
<a href="<%=request.getContextPath()%>/j_spring_security_logout">退出登录</a>
</body>
</html>
Java代码
IndexController.java
package com.spsecurity.xml.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/")
public class IndexController {
@RequestMapping("/login")
public String login(Model model, HttpServletRequest request) {
String msg = "";
String error = request.getParameter("error");
String logout = request.getParameter("logout");
if (error != null) {
msg = "用户名或者密码错误";
} else if (logout != null) {
msg = "退出登录成功";
}
model.addAttribute("msg", msg);
return "login";
}
@RequestMapping("/index")
public String index(String type) {
return "index";
}
}
使用注解方式
pom.xml引入依赖
与上面雷同,多一个tomcat插件配置
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
jsp页面
与上面相同,略
Java代码
IndexContoller.java 雷同,略
AppConfig.java
/**
* 对应 ContextLoaderListener的配置
*/
@Configuration
@ComponentScan(basePackages = "com.spsecurity.annotation", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class) })
public class AppConfig {
// 在此配置除了Controller的其它bean,比如:数据库链接池、事务管理、业务等。
}
MvcConfig.java
/**
* 对应DispatcherServlet配置
*/
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.spsecurity.annotation.controller", includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class) })
public class MvcConfig extends WebMvcConfigurerAdapter {
// 视图解析器
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
viewResolver.setViewClass(JstlView.class);
return viewResolver;
}
}
SecurityConfig.java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN").and().withUser("user")
.password("user").roles("USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/login").permitAll().antMatchers("/**").hasRole("ADMIN").and().formLogin()
.loginPage("/login").loginProcessingUrl("/j_spring_security_check").defaultSuccessUrl("/index")
.failureUrl("/login?error").usernameParameter("username").passwordParameter("password").and().logout()
.logoutUrl("/j_spring_security_logout").logoutSuccessUrl("/login?logout").and().csrf().disable();
}
/**
* 系统自带登录页面
*/
// @Override
// protected void configure(HttpSecurity http) throws Exception {
// http.authorizeRequests().antMatchers("/**").hasRole("ADMIN").and().formLogin().defaultSuccessUrl("/index").and()
// .logout().logoutUrl("/j_spring_security_logout").and().csrf();
// }
}
SpringSecurityInitializer.java
/**
* 创建一个扩展 AbstractSecurityWebApplicationInitializer 的一个类, 它将会自动地加载 springSecurityFilterChain<br/>
* 相当于web.xml中的配置 <br/>
* <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>
*/
public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {
}
WebInit.java
/**
* 相当于web.xml
*/
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {
// 指定rootContext的配置类
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { AppConfig.class };
}
// 指定servletContext的配置类
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { MvcConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
运行
tomcat7:run
URL权限控制
本案例没有使用springmvc,mybatis等框架。为了了解整体架构,尽可能使用默认配置。
数据库脚本
secuirty 默认表结构
可以根据需要修改
CREATE TABLE `users` (
`username` varchar(50) NOT NULL,
`password` varchar(50) NOT NULL,
`enabled` tinyint(1) NOT NULL,
PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `authorities` (
`username` varchar(50) NOT NULL,
`authority` varchar(50) NOT NULL,
UNIQUE KEY `ix_auth_username` (`username`,`authority`),
CONSTRAINT `fk_authorities_users` FOREIGN KEY (`username`) REFERENCES `users` (`username`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
新增表
CREATE TABLE `res` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT '',
`url` varchar(500) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
CREATE TABLE `role_res` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`role` varchar(50) NOT NULL,
`res_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_res_id` (`res_id`),
CONSTRAINT `fk_res_id` FOREIGN KEY (`res_id`) REFERENCES `res` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
数据
insert into `users`(`username`,`password`,`enabled`) values ('admin','hoiAYbOZ504w7urYx6q5Ig==',1),('xiaoming','XgTEgTOg7jji7+37gvsX3g==',1);
insert into `authorities`(`username`,`authority`) values ('admin','ADMIN'),('xiaoming','USER');
insert into `res`(`id`,`name`,`url`) values (1,'首页','/index.jsp'),(2,'管理页','/admin.jsp');
insert into `role_res`(`id`,`role`,`res_id`) values (1,'ADMIN',1),(2,'ADMIN',2),(3,'USER',1);
POM配置
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.1</version>
</dependency>
<!-- spring security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<!-- mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<!-- 数据源 -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
</dependencies>
<build>
<finalName>sec-web</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.2</version>
<configuration>
<target>1.8</target>
<source>1.8</source>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
项目开发
页面
新建页面index.jsp、login.jsp、 loginError.jsp、 accessDenied.jsp、 admin.jsp
login.jsp内容, 其它页面略
<body>
<form action="login.do" method="post">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username" /></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password" /></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="登录" />
<input type="reset" value="重置" />
</td>
</tr>
</table>
</form>
</body>
实体类
Res.java
private Integer id;
private String name;
private String url;
...
RoleRes.java
private Integer id;
private String role;
private Integer resId;
...
配置类
AuthenticationFailureHandlerImpl.java
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
response.sendRedirect(request.getContextPath() + "/loginError.jsp");
}
AuthenticationSuccessHandlerImpl.java
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.sendRedirect(request.getContextPath() + "/index.jsp");
}
UrlAccessDecisionManager.java
public class UrlAccessDecisionManager implements AccessDecisionManager {
@Override
public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException {
// 遍历角色
for (ConfigAttribute ca : configAttributes) {
// ① 当前url请求需要的权限
String needRole = ca.getAttribute();
if ("ROLE_LOGIN".equals(needRole)) {
if (authentication instanceof AnonymousAuthenticationToken) {
throw new BadCredentialsException("未登录!");
} else {
throw new AccessDeniedException("未授权该url!");
}
}
// ② 当前用户所具有的角色
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
for (GrantedAuthority authority : authorities) {
// 只要包含其中一个角色即可访问
if (authority.getAuthority().equals(needRole)) {
return;
}
}
}
throw new AccessDeniedException("请联系管理员分配权限!");
}
@Override
public boolean supports(ConfigAttribute attribute) {
return true;
}
@Override
public boolean supports(Class<?> clazz) {
return true;
}
}
UrlFilterInvocationSecurityMetadataSource.java
public class UrlFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
private JdbcDaoSupport dao;
public void setDao(JdbcDaoSupport dao) {
this.dao = dao;
}
@Override
public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
// 获取当前请求url
String requestUrl = ((FilterInvocation) object).getRequestUrl();
// 忽略url请放在此处进行过滤放行
List<String> paths = new ArrayList<>();
paths.add("/login.jsp");
paths.add("/loginError.jsp");
if (paths.contains(requestUrl)) {
return null;
}
// 数据库中所有url
List<Res> resList = dao.getJdbcTemplate().query("select id,url from res ", new RowMapper<Res>() {
@Override
public Res mapRow(ResultSet rs, int rowNum) throws SQLException {
Res res = new Res();
res.setId(rs.getInt(1));
res.setUrl(rs.getString(2));
return res;
}
});
for (Res res : resList) {
// 获取该url所对应的权限
if (requestUrl.equals(res.getUrl())) {
List<RoleRes> roleResList = dao.getJdbcTemplate().query(
"SELECT id,role,res_id FROM role_res where res_id = ?", new Integer[] { res.getId() },
new RowMapper<RoleRes>() {
@Override
public RoleRes mapRow(ResultSet rs, int rowNum) throws SQLException {
RoleRes rr = new RoleRes();
rr.setId(rs.getInt(1));
rr.setRole(rs.getString(2));
rr.setResId(rs.getInt(3));
return rr;
}
});
List<String> roles = new LinkedList<>();
if (!CollectionUtils.isEmpty(roleResList)) {
for (RoleRes r : roleResList) {
roles.add("ROLE_" + r.getRole());
}
}
// 保存该url对应角色权限信息
return SecurityConfig.createList(roles.toArray(new String[roles.size()]));
}
}
// 如果数据中没有找到相应url资源则为非法访问,要求用户登录再进行操作
return SecurityConfig.createList("ROLE_LOGIN");
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
@Override
public boolean supports(Class<?> clazz) {
return FilterInvocation.class.isAssignableFrom(clazz);
}
}
项目配置
连接数据库配置
基本信息
jdbc.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/test
jdbc.username=root
jdbc.password=mysql
Spring 连接数据库配置
applicationContext.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 加载基本信息 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 配置连接池属性 -->
<property name="driverClass" value="${jdbc.driverClassName}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
</beans>
Spring Security配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security" 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.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<security:http auto-config="false" entry-point-ref="authEntryPoint">
<!-- 表示匿名用户可以访问 -->
<security:intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<!-- 改变默认登出URL(/j_spring_security_logout,此URL失效) 为 /logout -->
<security:logout delete-cookies="JSESSIONID" logout-url="/logout" />
<!-- 添加自定义的AuthenticationFilter到FilterChain的FORM_LOGIN_FILTER位置 -->
<security:custom-filter ref="authenticationFilter" position="FORM_LOGIN_FILTER" />
<!-- 异常处理 -->
<security:custom-filter ref="exceptionTranslationFilter" after="EXCEPTION_TRANSLATION_FILTER" />
<!-- -->
<security:custom-filter ref="filterSecurityInterceptor" before="FILTER_SECURITY_INTERCEPTOR" />
</security:http>
<!-- AuthenticationEntryPoint,引导用户进行登录 -->
<bean id="authEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login.jsp" />
</bean>
<bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
<property name="authenticationEntryPoint" ref="authEntryPoint" />
<property name="accessDeniedHandler">
<bean class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<property name="errorPage" value="/accessDenied.jsp" />
</bean>
</property>
</bean>
<!-- 认证过滤器 -->
<bean id="authenticationFilter"
class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="usernameParameter" value="username" />
<property name="passwordParameter" value="password" />
<!-- 改变默认登录URL(/j_spring_security_check,此URL失效) 为 /login.do -->
<property name="filterProcessesUrl" value="/login.do" />
<property name="authenticationSuccessHandler" ref="authenticationSuccessHandler" />
<property name="authenticationFailureHandler" ref="authenticationFailureHandler" />
</bean>
<bean id="authenticationSuccessHandler" class="com.demo.security.config.AuthenticationSuccessHandlerImpl" />
<bean id="authenticationFailureHandler" class="com.demo.security.config.AuthenticationFailureHandlerImpl" />
<!-- 用于认证的AuthenticationManager -->
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider user-service-ref="userDetailsService">
<security:password-encoder hash="md5" base64="true">
<security:salt-source user-property="username" />
</security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
<bean id="userDetailsService" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource" ref="dataSource" />
<property name="rolePrefix" value="ROLE_" />
</bean>
<!-- 获取所配置资源访问的授权信息 -->
<bean id="filterSecurityInterceptor"
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager" />
<property name="accessDecisionManager" ref="accessDecisionManager" />
<property name="securityMetadataSource" ref="filterInvocationSecurityMetadataSource" />
</bean>
<bean id="accessDecisionManager" class="com.demo.security.config.UrlAccessDecisionManager" />
<bean id="filterInvocationSecurityMetadataSource"
class="com.demo.security.config.UrlFilterInvocationSecurityMetadataSource">
<property name="dao" ref="userDetailsService" />
</bean>
</beans>
Web配置
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext.xml,classpath:spring/spring-security.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<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>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
自定义过滤器链
web.xml 配置DelegatingFilterProxy 代理,spring-security.xml里通过FilterChainProxy配置具体的过滤器类。
pom.xml引用
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.1</version>
</dependency>
<!-- spring security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
<build>
<finalName>security-filter</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.2</version>
<configuration>
<target>1.8</target>
<source>1.8</source>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
web.xml配置
<web-app id="webId" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>Archetype Created Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-security.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<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>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
spring-security.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security" 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.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
<security:filter-chain-map path-type="ant">
<security:filter-chain pattern="/**"
filters="httpSessionContextFilter, logoutFilter, authenticationFilter, anonymousAuthenticationFilter, exceptionTranslationFilter, filterSecurityInterceptor" />
</security:filter-chain-map>
</bean>
<bean id="httpSessionContextFilter"
class="org.springframework.security.web.context.SecurityContextPersistenceFilter" />
<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg value="/logout.jsp" />
<constructor-arg>
<bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
</constructor-arg>
<property name="filterProcessesUrl" value="/logout" />
</bean>
<!-- 认证过滤器 -->
<bean id="authenticationFilter"
class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="usernameParameter" value="username" />
<property name="passwordParameter" value="password" />
<!-- 改变默认登录URL(/j_spring_security_check,此URL失效) 为 /login.do -->
<property name="filterProcessesUrl" value="/login.do" />
<property name="authenticationSuccessHandler" ref="authenticationSuccessHandler" />
<property name="authenticationFailureHandler" ref="authenticationFailureHandler" />
</bean>
<bean id="authenticationSuccessHandler" class="com.demo.security.config.AuthenticationSuccessHandlerImpl" />
<bean id="authenticationFailureHandler" class="com.demo.security.config.AuthenticationFailureHandlerImpl" />
<!-- 用于认证的AuthenticationManager -->
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider>
<security:user-service>
<security:user name="admin" password="123" authorities="ROLE_USER,ROLE_ADMIN" />
<security:user name="xiaoming" password="123" authorities="ROLE_USER" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
<bean id="anonymousAuthenticationFilter"
class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
<constructor-arg value="123" />
</bean>
<bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
<property name="authenticationEntryPoint" ref="authEntryPoint" />
<property name="accessDeniedHandler">
<bean class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<property name="errorPage" value="/accessDenied.jsp" />
</bean>
</property>
</bean>
<!-- AuthenticationEntryPoint,引导用户进行登录 -->
<bean id="authEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login.jsp" />
</bean>
<!-- 获取所配置资源访问的授权信息 -->
<bean id="filterSecurityInterceptor"
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager" />
<property name="accessDecisionManager" ref="accessDecisionManager" />
<property name="securityMetadataSource">
<security:filter-security-metadata-source>
<security:intercept-url pattern="/log**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<security:intercept-url pattern="/admin**" access="ROLE_ADMIN" />
<security:intercept-url pattern="/**" access="ROLE_USER" />
</security:filter-security-metadata-source>
</property>
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<property name="decisionVoters">
<list>
<bean class="org.springframework.security.access.vote.RoleVoter">
<property name="rolePrefix" value="" />
</bean>
<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</list>
</property>
</bean>
</beans>
Java类
AuthenticationFailureHandlerImpl.java
public class AuthenticationFailureHandlerImpl implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
response.sendRedirect(request.getContextPath() + "/loginError.jsp");
}
}
AuthenticationSuccessHandlerImpl.java
public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.sendRedirect(request.getContextPath() + "/index.jsp");
}
}
页面
accessDenied.jsp、admin.jsp、index.jsp、login.jsp、loginError.jsp
login.jsp如下,其它略
<body>
<form action="login.do" method="post">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username" /></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password" /></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="登录" />
<input type="reset" value="重置" />
</td>
</tr>
</table>
</form>
</body>

浙公网安备 33010602011771号