Loading... # 引言 我本身对于网络安全是比较感兴趣的,对于网络安全,当前时代还是蛮重要的,想到之前的毕业设计都是围绕着网络安全展开的,废话不多说,最近项目中用到了安全框架,所以进行总结一番。 # 依赖 当然,使用maven进行依赖管理还是非常方便的。这里附上我的pom文件 ```xml <?xml version="1.0" encoding="UTF-8"?> <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.alc</groupId> <artifactId>security</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <properties> <webVersion>3.0</webVersion> <spring.version>4.2.5.RELEASE</spring.version> </properties> <dependencies> <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> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.49</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>4.1.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>4.1.0.RELEASE</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <configuration> <!-- 指定端口 --> <port>9090</port> <!-- 请求路径 --> <path>/</path> </configuration> </plugin> </plugins> </build> </project> ``` # 配置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" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <context-param> <!-- 载入spring安全框架的xml文件 --> <param-name>contextConfigLocation</param-name> <param-value>classpath: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> </web-app> ``` # 配置spring-security.xml ```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.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd"> <!-- 配置不进行安全拦截的列表--> <!--一般是注册和登录以及不敏感的路径--> <!--还有一些静态资源,属于注册登陆页面需要用到的路径--> <!--可以使用*代表目录下的所有文件--> <http pattern="/favicon.ico" security="none"/> <http pattern="/login.html" security="none"/> <http pattern="/registry.html" security="none"/> <http pattern="/admin/login.do" security="none"/> <http pattern="/css/*" security="none"/> <http pattern="/js/*" security="none"/> <http pattern="/imgs/*" security="none"/> <!-- 页面拦截规则 --> <http use-expressions="false"> <!--使用SpEL表达式,这个表达式看起来很诡异,我不喜欢使用,等用到了时候再说吧--> <intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN"/> <!--拦截的路径,检查这个路径是否是当前角色--> <form-login login-page="/login.html" default-target-url="http://www.zunmx.top" always-use-default-target="true" authentication-failure-forward-url="/err.html" /> <!--1. 登录页面--> <!--2. 登陆成功后的目标地址--> <!--3. 登陆成功后是否转向默认地址--> <!--4. 登陆失败指向的地址--> <csrf disabled="true"/> <!--自身就进行了请求的校验,如果开启,可能会导致自身的一些问题,具体没有分析原因。--> </http> <!-- 认证管理器 --> <authentication-manager> <!--认证管理器--> <authentication-provider> <!--认证提供者--> <user-service> <!--用户服务--> <user name="admin" password="123456" authorities="ROLE_USER"/> <!--这里是写成了固定的admin==123465--> </user-service> </authentication-provider> </authentication-manager> </beans:beans> ``` # 升级版的认证管理器 我们肯定不希望走的固定值,最起码走的是数据库,所以配置成走数据库的。 ```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.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd"> <!--创建自己的认证方式--> <beans:bean id="myUserAuth" class="com.alc.auth"/> <!-- 配置不进行安全拦截的列表--> <!--一般是注册和登录以及不敏感的路径--> <!--还有一些静态资源,属于注册登陆页面需要用到的路径--> <!--可以使用*代表目录下的所有文件--> <http pattern="/favicon.ico" security="none"/> <http pattern="/login.html" security="none"/> <http pattern="/registry.html" security="none"/> <http pattern="/admin/login.do" security="none"/> <http pattern="/css/*" security="none"/> <http pattern="/js/*" security="none"/> <http pattern="/imgs/*" security="none"/> <!-- 页面拦截规则 --> <http use-expressions="false"> <!--使用SpEL表达式,这个表达式看起来很诡异,我不喜欢使用,等用到了时候再说吧--> <intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN"/> <!--拦截的路径,检查这个路径是否是当前角色--> <form-login login-page="/login.html" default-target-url="http://www.zunmx.top" always-use-default-target="true" authentication-failure-forward-url="/err.html" /> <!--1. 登录页面--> <!--2. 登陆成功后的目标地址--> <!--3. 登陆成功后是否转向默认地址--> <!--4. 登陆失败指向的地址--> <csrf disabled="true"/> <!--自身就进行了请求的校验,如果开启,可能会导致自身的一些问题,具体没有分析原因。--> </http> <!--加盐的加密算法--> <beans:bean id="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/> <!-- 认证管理器 --> <authentication-manager> <!--认证管理器--> <authentication-provider user-service-ref="myUserAuth"> <!--认证提供者,我们自己定义的实现类。--> <password-encoder ref="bcryptEncoder"/> <!--如果密码是加盐的加密算法,需要对密码进行处理--> </authentication-provider> </authentication-manager> </beans:beans> ``` # 定义自己的认证方式 也就是自定义的认证方式,我这里使用的是MySQL ```java package com.alc; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import java.sql.*; import java.util.ArrayList; import java.util.List; public class auth implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { try { // 感觉最近有点手生,用一下原生的jdbc叭 Class.forName("com.mysql.jdbc.Driver"); // 创建链接 Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/studentmanager", "custom", "1.2.3.4.5.6"); // 写SQL语句 String sql = "SELECT * FROM user WHERE username = ?"; // 预处理对象 PreparedStatement preparedStatement = conn.prepareStatement(sql); // 给预处理对象赋值 还没记错,参数从1开始 噗哈哈哈 preparedStatement.setString(1, username); // 获取结果集 ResultSet resultSet = preparedStatement.executeQuery(); // 遍历结果集, while (resultSet.next()) { // 获取密码 String password = resultSet.getString("password"); // 创建认证列表 List<GrantedAuthority> authorities = new ArrayList<>(); // 简单的身份认证,给这个人定义一个权限 GrantedAuthority role; if (resultSet.getString("power").equals("管理员")) { role = new SimpleGrantedAuthority("ROLE_ADMIN"); } else { role = new SimpleGrantedAuthority("ROLE_USER"); } // 存入列表里 authorities.add(role); // 返回一个用户信息 // * @return a fully populated user record (never <code>null</code>) 来源于接口文档 // User(String username, String password, // Collection<? extends GrantedAuthority> authorities) // 上面为什么需要list也源于这里 return new User(username, password, authorities); } // 发生异常就交给虚拟机处理吧,没有找到这个用户就算了。。。 return null; } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); // 异常的话就更不用说了,数据库都炸了。。。 return null; } } } ``` # 日志如下 ```java D:\Software\Java\jdk1.8.0_151\bin\java.exe -Dmaven.multiModuleProjectDirectory=E:\Workspace\train\security "-Dmaven.home=D:\Software\JetBrains\IntelliJ IDEA 2020.2.3\plugins\maven\lib\maven3" "-Dclassworlds.conf=D:\Software\JetBrains\IntelliJ IDEA 2020.2.3\plugins\maven\lib\maven3\bin\m2.conf" "-Dmaven.ext.class.path=D:\Software\JetBrains\IntelliJ IDEA 2020.2.3\plugins\maven\lib\maven-event-listener.jar" "-javaagent:D:\Software\JetBrains\IntelliJ IDEA 2020.2.3\lib\idea_rt.jar=5012:D:\Software\JetBrains\IntelliJ IDEA 2020.2.3\bin" -Dfile.encoding=UTF-8 -classpath "D:\Software\JetBrains\IntelliJ IDEA 2020.2.3\plugins\maven\lib\maven3\boot\plexus-classworlds-2.6.0.jar;D:\Software\JetBrains\IntelliJ IDEA 2020.2.3\plugins\maven\lib\maven3\boot\plexus-classworlds.license" org.codehaus.classworlds.Launcher -Didea.version=2020.2.3 -s D:\Software\apache-maven-3.6.3\conf\settings.xml -Dmaven.repo.local=D:\Software\apache-maven-3.6.3\repository tomcat7:run [INFO] Scanning for projects... [WARNING] [WARNING] Some problems were encountered while building the effective model for com.alc:security:war:1.0-SNAPSHOT [WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-compiler-plugin is missing. @ line 70, column 21 [WARNING] 'build.plugins.plugin.version' for org.apache.tomcat.maven:tomcat7-maven-plugin is missing. @ line 77, column 21 [WARNING] [WARNING] It is highly recommended to fix these problems because they threaten the stability of your build. [WARNING] [WARNING] For this reason, future Maven versions might no longer support building such malformed projects. [WARNING] [INFO] [INFO] --------------------------< com.alc:security >-------------------------- [INFO] Building security 1.0-SNAPSHOT [INFO] --------------------------------[ war ]--------------------------------- [INFO] [INFO] >>> tomcat7-maven-plugin:2.2:run (default-cli) > process-classes @ security >>> [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ security --- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] Copying 1 resource [INFO] [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ security --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] <<< tomcat7-maven-plugin:2.2:run (default-cli) < process-classes @ security <<< [INFO] [INFO] [INFO] --- tomcat7-maven-plugin:2.2:run (default-cli) @ security --- [INFO] Running war on http://localhost:9090/ [INFO] Using existing Tomcat server configuration at E:\Workspace\train\security\target\tomcat [INFO] create webapp with contextPath: 五月 11, 2021 2:12:59 上午 org.apache.coyote.AbstractProtocol init 信息: Initializing ProtocolHandler ["http-bio-9090"] 五月 11, 2021 2:12:59 上午 org.apache.catalina.core.StandardService startInternal 信息: Starting service Tomcat 五月 11, 2021 2:12:59 上午 org.apache.catalina.core.StandardEngine startInternal 信息: Starting Servlet Engine: Apache Tomcat/7.0.47 五月 11, 2021 2:13:00 上午 org.apache.catalina.core.ApplicationContext log 信息: No Spring WebApplicationInitializer types detected on classpath 五月 11, 2021 2:13:00 上午 org.apache.catalina.core.ApplicationContext log 信息: Initializing Spring root WebApplicationContext 五月 11, 2021 2:13:00 上午 org.springframework.web.context.ContextLoader initWebApplicationContext 信息: Root WebApplicationContext: initialization started 五月 11, 2021 2:13:00 上午 org.springframework.web.context.support.XmlWebApplicationContext prepareRefresh 信息: Refreshing Root WebApplicationContext: startup date [Tue May 11 02:13:00 CST 2021]; root of context hierarchy 五月 11, 2021 2:13:00 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [spring-security.xml] 五月 11, 2021 2:13:00 上午 org.springframework.security.core.SpringSecurityCoreVersion performVersionChecks 信息: You are running with Spring Security Core 4.1.0.RELEASE 五月 11, 2021 2:13:00 上午 org.springframework.security.config.SecurityNamespaceHandler <init> 信息: Spring Security 'config' module version is 4.1.0.RELEASE 五月 11, 2021 2:13:01 上午 org.springframework.security.config.http.HttpSecurityBeanDefinitionParser checkFilterChainOrder 信息: Checking sorted filter chain: [Root bean: class [org.springframework.security.web.context.SecurityContextPersistenceFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 200, Root bean: class [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 400, Root bean: class [org.springframework.security.web.header.HeaderWriterFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 500, <org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#0>, order = 1100, Root bean: class [org.springframework.security.web.savedrequest.RequestCacheAwareFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 1600, Root bean: class [org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 1700, Root bean: class [org.springframework.security.web.authentication.AnonymousAuthenticationFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 2000, Root bean: class [org.springframework.security.web.session.SessionManagementFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 2100, Root bean: class [org.springframework.security.web.access.ExceptionTranslationFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 2200, <org.springframework.security.web.access.intercept.FilterSecurityInterceptor#0>, order = 2300] 五月 11, 2021 2:13:01 上午 org.springframework.security.web.DefaultSecurityFilterChain <init> 信息: Creating filter chain: Ant [pattern='/favicon.ico'], [] 五月 11, 2021 2:13:01 上午 org.springframework.security.web.DefaultSecurityFilterChain <init> 信息: Creating filter chain: Ant [pattern='/login.html'], [] 五月 11, 2021 2:13:01 上午 org.springframework.security.web.DefaultSecurityFilterChain <init> 信息: Creating filter chain: Ant [pattern='/registry.html'], [] 五月 11, 2021 2:13:01 上午 org.springframework.security.web.DefaultSecurityFilterChain <init> 信息: Creating filter chain: Ant [pattern='/admin/login.do'], [] 五月 11, 2021 2:13:01 上午 org.springframework.security.web.DefaultSecurityFilterChain <init> 信息: Creating filter chain: Ant [pattern='/css/*'], [] 五月 11, 2021 2:13:01 上午 org.springframework.security.web.DefaultSecurityFilterChain <init> 信息: Creating filter chain: Ant [pattern='/js/*'], [] 五月 11, 2021 2:13:01 上午 org.springframework.security.web.DefaultSecurityFilterChain <init> 信息: Creating filter chain: Ant [pattern='/imgs/*'], [] 五月 11, 2021 2:13:01 上午 org.springframework.security.web.DefaultSecurityFilterChain <init> 信息: Creating filter chain: org.springframework.security.web.util.matcher.AnyRequestMatcher@1, [org.springframework.security.web.context.SecurityContextPersistenceFilter@b25cb42, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@66366fff, org.springframework.security.web.header.HeaderWriterFilter@4ce247a2, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@47bf8e75, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@6265221b, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@3779e03f, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@69787e25, org.springframework.security.web.session.SessionManagementFilter@520f9959, org.springframework.security.web.access.ExceptionTranslationFilter@19b10cf9, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@61b16fe8] 五月 11, 2021 2:13:01 上午 org.springframework.security.config.http.DefaultFilterChainValidator checkLoginPageIsntProtected 信息: Checking whether login URL '/login.html' is accessible with your configuration 五月 11, 2021 2:13:01 上午 org.springframework.web.context.ContextLoader initWebApplicationContext 信息: Root WebApplicationContext: initialization completed in 597 ms 五月 11, 2021 2:13:01 上午 org.apache.coyote.AbstractProtocol start 信息: Starting ProtocolHandler ["http-bio-9090"] Tue May 11 02:13:05 CST 2021 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification. Tue May 11 02:13:09 CST 2021 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification. ``` # 演示样例 ![请输入图片描述](https://www.zunmx.top/usr/uploads/2021/05/2350397723.gif) © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏