Spring 安全实例教程

Spring Security 提供了在 Web 应用程序中执行身份验证和授权的方法,我们可以在任何基于服务器的 Web 应用程序中使用 Spring Security。

春季安全

spring security example tutorial Some of the benefits of using Spring Security are:

安全是我们需要特别注意的地方,否则我们的应用程序将对攻击者易受攻击 2. 防止一些常见的攻击,如CSRF,会话固定攻击 3. 易于集成到任何Web应用程序。 我们不需要修改Web应用程序配置,春天自动向Web应用程序注入安全过滤器 4. 通过不同的方式提供认证支持 - 内存,DAO,JDBC,LDAP和更多 5. 提供无视URL特定的模式的选项,为良好的静态HTML服务,图像文件 6. 支持群组和角色

春季安全示例

We will create a web application and integrate it with Spring Security. Create a web application using "Dynamic Web Project" option in Eclipse, so that our skeleton web application is ready. Make sure to convert it to maven project because we are using Maven for build and deployment. If you are unfamiliar with these steps, please refer Java Web Application Tutorial. Once we will have our application secured, final project structure will look like below image. Spring Security Example Tutorial We will look into three spring security authentication methods.

二、二、二、二、二、三、三、三、三、三、三、三、三、三、三、三、三、三、三、三、三、三、三、三、三、三、三、三、三、三、三、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四、四

对于JDBC,我正在使用MySQL数据库,并执行以下脚本来创建用户详细表。

 1CREATE TABLE `Employees` (
 2  `username` varchar(20) NOT NULL DEFAULT '',
 3  `password` varchar(20) NOT NULL DEFAULT '',
 4  `enabled` tinyint(1) NOT NULL DEFAULT '1',
 5  PRIMARY KEY (`username`)
 6) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 7
 8CREATE TABLE `Roles` (
 9  `username` varchar(20) NOT NULL DEFAULT '',
10  `role` varchar(20) NOT NULL DEFAULT '',
11  PRIMARY KEY (`username`,`role`)
12) ENGINE=InnoDB DEFAULT CHARSET=utf8;
13
14INSERT INTO `Employees` (`username`, `password`, `enabled`)
15VALUES
16    ('pankaj', 'pankaj123', 1);
17
18INSERT INTO `Roles` (`username`, `role`)
19VALUES
20    ('pankaj', 'Admin'),
21    ('pankaj', 'CEO');
22
23commit;

我们还需要将 JDBC DataSource 配置为 JNDI 在我们的 servlet 容器中,请阅读 Tomcat JNDI DataSource 示例来了解这一点。

春季安全 Maven 依赖

这里是我们最后的 pom.xml 文件。

 1<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
 2    xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 3    <modelVersion>4.0.0</modelVersion>
 4    <groupId>WebappSpringSecurity</groupId>
 5    <artifactId>WebappSpringSecurity</artifactId>
 6    <version>0.0.1-SNAPSHOT</version>
 7    <packaging>war</packaging>
 8    <dependencies>
 9    	<!-- Spring Security Artifacts - START -->
10    	<dependency>
11    		<groupId>org.springframework.security</groupId>
12    		<artifactId>spring-security-web</artifactId>
13    		<version>3.2.3.RELEASE</version>
14    	</dependency>
15    	<dependency>
16    		<groupId>org.springframework.security</groupId>
17    		<artifactId>spring-security-config</artifactId>
18    		<version>3.2.3.RELEASE</version>
19    	</dependency>
20    	<dependency>
21    		<groupId>org.springframework.security</groupId>
22    		<artifactId>spring-security-taglibs</artifactId>
23    		<version>3.0.5.RELEASE</version>
24    	</dependency>
25    	<!-- Spring Security Artifacts - END -->
26
27    	<dependency>
28    		<groupId>javax.servlet</groupId>
29    		<artifactId>jstl</artifactId>
30    		<version>1.2</version>
31    		<scope>compile</scope>
32    	</dependency>
33    	<dependency>
34    		<groupId>javax.servlet.jsp</groupId>
35    		<artifactId>jsp-api</artifactId>
36    		<version>2.1</version>
37    		<scope>provided</scope>
38    	</dependency>
39    	<dependency>
40    		<groupId>javax.servlet</groupId>
41    		<artifactId>javax.servlet-api</artifactId>
42    		<version>3.0.1</version>
43    		<scope>provided</scope>
44    	</dependency>
45    	<dependency>
46    		<groupId>commons-logging</groupId>
47    		<artifactId>commons-logging</artifactId>
48    		<version>1.1.1</version>
49    	</dependency>
50    	<dependency>
51    		<groupId>org.springframework</groupId>
52    		<artifactId>spring-jdbc</artifactId>
53    		<version>4.0.2.RELEASE</version>
54    	</dependency>
55    </dependencies>
56    <build>
57    	<sourceDirectory>src</sourceDirectory>
58    	<plugins>
59    		<plugin>
60    			<artifactId>maven-compiler-plugin</artifactId>
61    			<version>3.1</version>
62    			<configuration>
63    				<source>1.7</source>
64    				<target>1.7</target>
65    			</configuration>
66    		</plugin>
67    		<plugin>
68    			<artifactId>maven-war-plugin</artifactId>
69    			<version>2.3</version>
70    			<configuration>
71    				<warSourceDirectory>WebContent</warSourceDirectory>
72    				<failOnMissingWebXml>false</failOnMissingWebXml>
73    			</configuration>
74    		</plugin>
75    	</plugins>
76    </build>
77</project>

我们遵循与春季框架相关的依赖。

  1. spring-jdbc:这被用于JDBC身份验证方法的操作。它需要作为JNDI的DataSource设置。 对于其使用的完整示例,请参阅 Spring DataSource JNDI Example
  2. spring-security-taglibs:春节安全标签库,我已经用它来显示用户角色在JSP页面上。 大多数时候,你不会需要它虽然
  3. spring-security-config:它用于配置身份验证提供商,无论是使用JDBC,DAO,LDAP等( _4)。 **spring-

另外,请注意,我们将使用Servlet API 3.0功能来通过编程添加听器和过滤器,这就是为什么Servlet API版本在依赖中应该是 3.0 或更高版本的原因。

春季安全示例 查看页面

我们在我们的应用程序中有JSP和HTML页面,我们希望在HTML以外的所有页面中应用身份验证。

 1<!DOCTYPE html>
 2<html>
 3<head>
 4<meta charset="UTF-8">
 5<title>Health Check</title>
 6</head>
 7<body>
 8    <h3>Service is up and running!!</h3>
 9</body>
10</html>

《index.jsp》

 1<%@ page language="java" contentType="text/html; charset=UTF-8"
 2    pageEncoding="UTF-8"%>
 3<%@ taglib uri="https://java.sun.com/jsp/jstl/core" prefix="c" %>
 4<%@ taglib uri="https://www.springframework.org/security/tags" prefix="sec" %>
 5<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
 6<html>
 7<head>
 8<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 9<title>Home Page</title>
10</head>
11<body>
12<h3>Home Page</h3>
13
14    <p>
15      Hello <b><c:out value="${pageContext.request.remoteUser}"/></b><br>
16      Roles: <b><sec:authentication property="principal.authorities" /></b>
17    </p>
18
19    <form action="logout" method="post">
20      <input type="submit" value="Logout" />
21      <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
22    </form>
23</body>
24</html>

我在应用程序部署描述器中包含了index.jsp作为欢迎文件。Spring Security 处理 CSRF 攻击,所以当我们提交登录表格时,我们正在将 CSRF 代币发送回服务器来删除它。Spring Security 组件设置的 CSRF 对象是 _csrf,我们正在使用其属性名称和代币值来传递登录请求。

春季安全示例 UserDetailsService DAO 实施

由于我们还将使用基于DAO的身份验证,我们需要实施UserDetailsService接口并提供loadUserByUsername()方法的实现。

 1package com.journaldev.webapp.spring.dao;
 2
 3import java.util.Collection;
 4import java.util.List;
 5
 6import org.apache.commons.logging.Log;
 7import org.apache.commons.logging.LogFactory;
 8import org.springframework.security.core.GrantedAuthority;
 9import org.springframework.security.core.authority.SimpleGrantedAuthority;
10import org.springframework.security.core.userdetails.UserDetails;
11import org.springframework.security.core.userdetails.UserDetailsService;
12import org.springframework.security.core.userdetails.UsernameNotFoundException;
13
14public class AppUserDetailsServiceDAO implements UserDetailsService {
15
16    protected final Log logger = LogFactory.getLog(getClass());
17    
18    @Override
19    public UserDetails loadUserByUsername(final String username)
20    		throws UsernameNotFoundException {
21    	
22    	logger.info("loadUserByUsername username="+username);
23    	
24    	if(!username.equals("pankaj")){
25    		throw new UsernameNotFoundException(username + " not found");
26    	}
27    	
28    	//creating dummy user details, should do JDBC operations
29    	return new UserDetails() {
30    		
31    		private static final long serialVersionUID = 2059202961588104658L;
32
33    		@Override
34    		public boolean isEnabled() {
35    			return true;
36    		}
37    		
38    		@Override
39    		public boolean isCredentialsNonExpired() {
40    			return true;
41    		}
42    		
43    		@Override
44    		public boolean isAccountNonLocked() {
45    			return true;
46    		}
47    		
48    		@Override
49    		public boolean isAccountNonExpired() {
50    			return true;
51    		}
52    		
53    		@Override
54    		public String getUsername() {
55    			return username;
56    		}
57    		
58    		@Override
59    		public String getPassword() {
60    			return "pankaj123";
61    		}
62    		
63    		@Override
64    		public Collection<? extends GrantedAuthority> getAuthorities() {
65    			List<SimpleGrantedAuthority> auths = new java.util.ArrayList<SimpleGrantedAuthority>();
66    			auths.add(new SimpleGrantedAuthority("admin"));
67    			return auths;
68    		}
69    	};
70    }
71
72}

请注意,我正在创建一个匿名的UserDetails内部类,然后返回它. 您可以为它创建一个实现类,然后实例化并返回它。

春季安全示例 WebSecurityConfigurer 实施

我们可以实现WebSecurityConfigurer接口,或者我们可以扩展基本实现类WebSecurityConfigurerAdapter,并覆盖方法。

 1package com.journaldev.webapp.spring.security;
 2
 3import javax.naming.Context;
 4import javax.naming.InitialContext;
 5import javax.sql.DataSource;
 6
 7import org.springframework.context.annotation.Configuration;
 8import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
 9import org.springframework.security.config.annotation.web.builders.WebSecurity;
10import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
11import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
12
13import com.journaldev.webapp.spring.dao.AppUserDetailsServiceDAO;
14
15@Configuration
16@EnableWebSecurity
17public class SecurityConfig extends WebSecurityConfigurerAdapter {
18
19    @Override
20    public void configure(AuthenticationManagerBuilder auth)
21    		throws Exception {
22
23    	// in-memory authentication
24    	// auth.inMemoryAuthentication().withUser("pankaj").password("pankaj123").roles("USER");
25
26    	// using custom UserDetailsService DAO
27    	// auth.userDetailsService(new AppUserDetailsServiceDAO());
28
29    	// using JDBC
30    	Context ctx = new InitialContext();
31    	DataSource ds = (DataSource) ctx
32    			.lookup("java:/comp/env/jdbc/MyLocalDB");
33
34    	final String findUserQuery = "select username,password,enabled "
35    			+ "from Employees " + "where username = ?";
36    	final String findRoles = "select username,role " + "from Roles "
37    			+ "where username = ?";
38    	
39    	auth.jdbcAuthentication().dataSource(ds)
40    			.usersByUsernameQuery(findUserQuery)
41    			.authoritiesByUsernameQuery(findRoles);
42    }
43    
44    @Override
45    public void configure(WebSecurity web) throws Exception {
46        web
47            .ignoring()
48                // Spring Security should completely ignore URLs ending with .html
49                .antMatchers("/*.html");
50    }
51
52}

请注意,我们正在忽略所有HTML文件,通过配置(WebSecurity)方法。代码显示如何插入JDBC身份验证。我们需要通过提供DataSource来配置。由于我们正在使用自定义表,我们还需要提供选定的查询以获取用户细节和它的角色。配置内存和DAO基于身份验证很容易,它们在上面的代码中被评论。您可以不评论使用它们,确保一次只有一个配置。 @Configuration@EnableWebSecurity注释是必需的,所以春季框架知道这个类将用于春季安全配置。春季安全配置是使用[Builder Pattern](/community/tutorials/builder-design-pattern-in-we-builderBuild Design Pattern in Java)和基于

将Spring Security Web与Servlet API集成

最后一部分是将我们的春季安全配置类集成到Servlet API. 可以通过扩展‘AbstractSecurityWebApplicationInitializer’类并在超级类构建器中传输安全配置类来轻松完成。

 1package com.journaldev.webapp.spring.security;
 2
 3import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
 4
 5public class SecurityWebApplicationInitializer extends
 6    	AbstractSecurityWebApplicationInitializer {
 7
 8    public SecurityWebApplicationInitializer() {
 9        super(SecurityConfig.class);
10    }
11}

當我們的背景啟動時,它使用ServletContext添加 [ContextLoaderListener listener](/community/tutorials/servletcontextlistener-servlet-listener-example "Servlet Listener Example – ServletContextListener, HttpSessionListener 和 ServletRequestListener)並註冊我們的配置類別為 Servlet Filter,這只會在Servlet-3投訴伺服器容器中工作。因此,如果您正在使用Apache Tomcat,請確保它是7.0或更高版本。我們的項目準備好,只需

访问没有安全性的HTML页面

Spring Security ignore

身份验证失败 坏身份验证

Spring Security Example Bad Credentials

使用 Spring 安全 JDBC 身份验证

Spring Security JDBC

首页 使用 Spring Security 用户详细信息服务 DAO 身份验证

Spring Security DAO

使用 Spring 安全性内存身份验证

Spring Security Example In Memory

逻辑页面

Spring Security Form Logout If you want to use Servlet Container that doesn't support Servlet Specs 3, then you would need to register DispatcherServlet through deployment descriptor. See JavaDoc of WebApplicationInitializer for more details. That's all for Spring Security example tutorial and it's integration in Servlet Based Web Application. Please download the sample project from below link and play around with it to learn more.

下载Spring Servlet Security Project

Published At
Categories with 技术
Tagged with
comments powered by Disqus