简单的Spring Security实例(自定义登录验证)
来源:互联网 发布:思科网络课程 编辑:程序博客网 时间:2024/04/29 20:33
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
目录结构
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.xyc</groupId> <artifactId>spring.security</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>spring.security Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.2.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-core --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>4.1.2.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>4.1.2.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>4.1.2.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> <build> <finalName>spring.security</finalName> </build></project>
spring-servlet.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" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 设置使用注解的类所在的jar包 --> <context:component-scan base-package="com.xyc.spring.security"></context:component-scan> <!-- 启用spring mvc 注解 --> <mvc:annotation-driven/> <!-- 对转向页面的路径解析。prefix:前缀, suffix:后缀 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/view/" /> <property name="suffix" value=".jsp" /> </bean></beans>
spring-security.xml
<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 pattern="/user/loginPage" security="none" /> <security:http auto-config="true" use-expressions="true"> <security:intercept-url pattern="/**" access="hasRole('ROLE_USER')"/> <security:form-login login-page="/user/loginPage" authentication-failure-url="/user/loginPage?error=error" default-target-url="/user/index" login-processing-url="/login"/> <security:logout invalidate-session="true" logout-success-url="/user/loginPage" logout-url="/logout"/> <security:csrf disabled="true"/> </security:http> <bean id="loginUserDetailService" class="com.xyc.spring.security.config.impl.LoginUserDetailsServiceImpl"></bean> <bean id="loginAuthenticationProvider" class="com.xyc.spring.security.config.LoginAuthenticationProvider"> <property name="userDetailsService" ref="loginUserDetailService"></property> </bean> <security:authentication-manager alias="myAuthenticationManager"> <security:authentication-provider ref="loginAuthenticationProvider"> </security:authentication-provider> </security:authentication-manager></beans>
web.xml
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" ><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" id="WebApp_ID" version="2.5"> <display-name>Spring Security</display-name> <welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list> <!-- Spring MVC配置 --> <!-- ====================================== --> <servlet> <servlet-name>spring</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 可以自定义servlet.xml配置文件的位置和名称,默认为WEB-INF目录下,名称为[<servlet-name>]-servlet.xml,如spring-servlet.xml--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- Spring Security begin --> <context-param> <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> <!-- Spring Security end --></web-app>
LoginUser
package com.xyc.spring.security.entity;/** * Created by xyc on 2016/8/22 0022. */public class LoginUser { private Long id; private String username; private String password; public LoginUser() { } public LoginUser(Long id, String username, String password) { this.id = id; this.username = username; this.password = password; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; }}
LoginAuthenticationProvider
package com.xyc.spring.security.config;/** * Created by xyc on 2016/8/22 0022. */import org.springframework.security.authentication.AuthenticationServiceException;import org.springframework.security.authentication.BadCredentialsException;import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;import org.springframework.security.authentication.dao.SaltSource;import org.springframework.security.authentication.encoding.PasswordEncoder;import org.springframework.security.authentication.encoding.PlaintextPasswordEncoder;import org.springframework.security.core.AuthenticationException;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.core.userdetails.UsernameNotFoundException;import org.springframework.util.Assert;/** * 重写DaoAuthenticationProvider的验证方法 */public class LoginAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider { private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder(); private SaltSource saltSource; private LoginUserDetailsService userDetailsService; protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { Object salt = null; if (this.saltSource != null) { salt = this.saltSource.getSalt(userDetails); } if (authentication.getCredentials() == null) { logger.debug("Authentication failed: no credentials provided"); throw new BadCredentialsException("Bad credentials:" + userDetails); } String presentedPassword = authentication.getCredentials().toString(); if (!passwordEncoder.isPasswordValid(userDetails.getPassword(), presentedPassword, salt)) { logger.debug("Authentication failed: password does not match stored value"); throw new BadCredentialsException("Bad credentials:" + userDetails); } } protected void doAfterPropertiesSet() throws Exception { Assert.notNull(this.userDetailsService, "A UserDetailsService must be set"); } protected PasswordEncoder getPasswordEncoder() { return passwordEncoder; } protected SaltSource getSaltSource() { return saltSource; } protected LoginUserDetailsService getUserDetailsService() { return userDetailsService; } protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { UserDetails loadedUser; try { String password = (String) authentication.getCredentials(); /** * 区别:这里使用的是自定义的验证方法 */ loadedUser = getUserDetailsService().loadUserByUsername(username, password); } catch (UsernameNotFoundException notFound) { throw notFound; } catch (Exception repositoryProblem) { throw new AuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem); } if (loadedUser == null) { throw new AuthenticationServiceException( "UserDetailsService returned null, which is an interface contract violation"); } return loadedUser; } /** * Sets the PasswordEncoder instance to be used to encode and validate * passwords. If not set, the password will be compared as plain text. * <p> * For systems which are already using salted password which are encoded * with a previous release, the encoder should be of type * {@code org.springframework.security.authentication.encoding.PasswordEncoder} * . Otherwise, the recommended approach is to use * {@code org.springframework.security.crypto.password.PasswordEncoder}. * * @param passwordEncoder must be an instance of one of the {@code PasswordEncoder} * types. */ public void setPasswordEncoder(Object passwordEncoder) { Assert.notNull(passwordEncoder, "passwordEncoder cannot be null"); if (passwordEncoder instanceof PasswordEncoder) { this.passwordEncoder = (PasswordEncoder) passwordEncoder; return; } if (passwordEncoder instanceof org.springframework.security.crypto.password.PasswordEncoder) { final org.springframework.security.crypto.password.PasswordEncoder delegate = (org.springframework.security.crypto.password.PasswordEncoder) passwordEncoder; this.passwordEncoder = new PasswordEncoder() { private void checkSalt(Object salt) { Assert.isNull(salt, "Salt value must be null when used with crypto module PasswordEncoder"); } public String encodePassword(String rawPass, Object salt) { checkSalt(salt); return delegate.encode(rawPass); } public boolean isPasswordValid(String encPass, String rawPass, Object salt) { checkSalt(salt); return delegate.matches(rawPass, encPass); } }; return; } throw new IllegalArgumentException("passwordEncoder must be a PasswordEncoder instance"); } /** * The source of salts to use when decoding passwords. <code>null</code> is * a valid value, meaning the <code>DaoAuthenticationProvider</code> will * present <code>null</code> to the relevant <code>PasswordEncoder</code>. * <p> * Instead, it is recommended that you use an encoder which uses a random * salt and combines it with the password field. This is the default * approach taken in the * {@code org.springframework.security.crypto.password} package. * * @param saltSource to use when attempting to decode passwords via the * <code>PasswordEncoder</code> */ public void setSaltSource(SaltSource saltSource) { this.saltSource = saltSource; } public void setUserDetailsService(LoginUserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; }}
LoginUserDetailsImpl
package com.xyc.spring.security.config;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.userdetails.User;import org.springframework.security.core.userdetails.UserDetails;import java.util.ArrayList;import java.util.Collection;/** * Created by xyc on 2016/8/22 0022. */public class LoginUserDetailsImpl extends User implements UserDetails { private static final long serialVersionUID = -5424897749887458053L; public LoginUserDetailsImpl(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) { super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities); } public LoginUserDetailsImpl(String username, String password, Collection<? extends GrantedAuthority> authorities) { super(username, password, authorities); } public LoginUserDetailsImpl(String username, String password) { super(username, password, new ArrayList<GrantedAuthority>()); }}
LoginUserDetailsService
package com.xyc.spring.security.config;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.core.userdetails.UsernameNotFoundException;/** * Created by xyc on 2016/8/22 0022. */public interface LoginUserDetailsService { /** * 根据用户名密码验证用户信息 * @param username 用户名 * @param password 密码 * @return * @throws UsernameNotFoundException */ UserDetails loadUserByUsername(String username, String password) throws UsernameNotFoundException;}
LoginUserDetailsServiceImpl
package com.xyc.spring.security.config.impl;import com.xyc.spring.security.config.LoginUserDetailsImpl;import com.xyc.spring.security.config.LoginUserDetailsService;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.UsernameNotFoundException;import java.util.ArrayList;import java.util.Collection;/** * Created by xyc on 2016/8/22 0022. */public class LoginUserDetailsServiceImpl implements LoginUserDetailsService { /** * 进行登录验证 */ public UserDetails loadUserByUsername(String username, String password) throws UsernameNotFoundException { boolean result = this.validate(username, password); if (!result) { return null; } Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); authorities.add(new SimpleGrantedAuthority("ROLE_USER")); LoginUserDetailsImpl user = new LoginUserDetailsImpl(username, password,authorities); return user; } /** * 在此处验证 * @param username * @param password * @return */ private boolean validate(String username, String password) { /** * 此处应该在数据库获取用户信息进行验证 */ if ("xyc".equals(username) && "123".equals(password)) { return true; } return false; }}
UserController
package com.xyc.spring.security.web;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;/** * Created by xyc on 2016/8/20 0020. */@Controller@RequestMapping(value = {"/","/user"})public class UserController { @RequestMapping(value = {"/","/index"},method = RequestMethod.GET) public String index(){ System.out.println("主页"); return "index"; } @RequestMapping(value = "/loginPage",method = RequestMethod.GET) public String loginPage(@RequestParam(value = "error", required = false) String error, Model model){ System.out.println("登录页"); if (error != null) { return "loginFailure"; } return "login"; }}
index.jsp
<%-- Created by IntelliJ IDEA. User: xyc Date: 2016/8/21 0021 Time: 10:31 To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <title>主页</title></head><body style="text-align: center;margin-top: 300px;"> <h4>**您好!您已成功登陆本系统!<a href="/logout">退出系统</a></h4></body></html>
login.jsp
<%-- Created by IntelliJ IDEA. User: xyc Date: 2016/8/21 0021 Time: 10:31 To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <title>登录</title></head><body style="text-align: center;margin-top: 300px;"><form method="post" action="/login"> <h4>登录模块</h4> <div> <input type="text" name="username" placeholder="用户名"> <input type="password" name="password" placeholder="密码"> <input type="submit" value="登录" name="submit"> </div></form></body></html>
loginFailure.jsp
<%-- Created by IntelliJ IDEA. User: xyc Date: 2016/8/22 0022 Time: 14:27 To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <title>登录失败</title></head><body style="text-align: center;margin-top: 300px;"> <h4>登录失败!请<a href="/user/loginPage">点击这里</a>重新登陆!</h4></body></html>
运行测试
运行项目,项目启动后默认打开地址:http://localhost:8080/user/loginPage
输入错误用户名:hehe和密码:haha,此时登录失败,跳转到错误提示页面(http://localhost:8080/user/loginPage?error=error)
点击”点击这里”重新跳转到登录页面,输入正确用户名:xyc,密码:123,此时验证通过,跳转到主页(http://localhost:8080/)
点击”退出系统”,返回登录页面
以上就是简单的Spring Security实例。。。
0 0
- 简单的Spring Security实例(自定义登录验证)
- spring security 登录验证
- spring Security 登录验证
- spring security登录验证
- 简单说说Spring Security 使用(附加验证码登录,自定义认证)
- Spring Security 自定义登录验证与自定义回调地址
- Spring Security 自定义登录验证与自定义回调地址
- spring security 自定义验证
- spring security简单实例
- Spring Security 3.1 登录验证
- spring security 登录验证 感想
- Spring Security 基础登录实例
- Spring Security 3.1自定义登录
- spring security 自定义认证登录
- Spring Security教程(10)---- 自定义登录成功后的处理程序及修改默认验证地址
- Spring Security教程(10)---- 自定义登录成功后的处理程序及修改默认验证地址
- Spring Security教程(10)---- 自定义登录成功后的处理程序及修改默认验证地址
- Spring Security教程(10)---- 自定义登录成功后的处理程序及修改默认验证地址
- POJ 3250 Bad Hair Day (栈的简单应用)
- 应用程序的并行配置不正确 sxstrace.exe
- java 爬虫
- 最新lnmp安装(nginx1.10,php7 ,mysql5.5)
- 数据库学习之num2
- 简单的Spring Security实例(自定义登录验证)
- 关于收集器采用的算法
- 【OK6410裸机程序】按键中断
- JavaEE获取资源(通过路径/通过域名)
- 一周工作小贴士(2016-8-28)
- 【Linux开发】V4L2驱动框架分析学习
- android开发多个Edittext相互监听
- Regionals 2015 :: Asia - Taipei 部分题解
- Spring(二)