Spring学习之旅(八) Spring Security的使用
来源:互联网 发布:w3c php手册下载 编辑:程序博客网 时间:2024/05/17 16:43
辛苦堆砌,转载请注明出处,谢谢!
之前的User校验我们自己通过比较用户名和密码来完成,这样可能存在一些安全隐患,还需要自己处理Session的问题。本篇文章使用Spring Security进行安全校验,对项目进行重构。
Spring Security是Spring实现的安全框架,可以对请求和方法进行安全保护,Spring Security根本上是一套Filter链,当配置使用Spring Security时,Spring会向项目中添加Filter,从而对请求进行拦截,并进行必要的安全校验。
首先,为了让Spring支持Spring Security,需要添加必要的依赖,这是因为Spring Security不属于Spring Framework,是一个独立的项目。
<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-web</artifactId><version>${spring-security-web.version}</version></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-config</artifactId><version>${spring-security-web.version}</version></dependency>然后,创建如下的类
package com.yjp.springmvc.blog.config;import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;public class SecurityWebInitializer extends AbstractSecurityWebApplicationInitializer {}该类派生自AbstractSecurityWebApplicationInitializer,这样,当启用Spring Security时,会加入安全校验需要的Filter链。最后,启用Spring Security,并配置拦截规则和用户数据源
package com.yjp.springmvc.blog.config;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Configuration;import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;import org.springframework.security.core.userdetails.UserDetailsService;@Configuration@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate UserDetailsService userDetailsService;@Overrideprotected void configure(HttpSecurity http) throws Exception {//配置拦截规则http.formLogin().loginPage("/login").failureUrl("/loginError").and().logout().logoutSuccessUrl("/login").and().authorizeRequests().antMatchers("/").authenticated().antMatchers("/**").permitAll();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService);}}我们派生了WebSecurityConfigurerAdapter类,并重新实现了两个方法,其中,configure以HttpSecurity为参数的方法,用来定制拦截规则,我们这里拦截"/"请求,其他请求放行,然后通过表单认证,认证表单为login,验证失败进入loginError请求,注销时,默认会进入logout请求,注销成功跳转到login请求。通过configure以AuthenticationManagerBuilder为参数的方法,我们返回数据源,数据源Spring会从UserDetailsService获取。记得将该配置类引入到RootConfig中。
下面调整我们之前的项目,删除LoginController,创建SecurityController
package com.yjp.springmvc.blog.web.controller;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;@Controllerpublic class SecurityController {@RequestMapping(method=RequestMethod.GET, value="/login")public String login(String error) {return "login";}@RequestMapping(method=RequestMethod.GET, value="/loginError")public String loginError(Model model) {model.addAttribute("error", "用户名或密码错误");return "login";}}主要用来处理login流程的请求,将请求与对应的视图挂钩,看看login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ page isELIgnored="false"%><!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>简微</title><link rel="stylesheet" type="text/css" href="resources/css/login.css"><link rel="stylesheet" type="text/css" href="resources/css/error.css"></head><body><div class="loginPanel"> <div> <img src="resources/images/logo.png" alt="简微"/> </div> <form method="post" action="login"> <table> <tr> <td colspan="2" align="center" style="font-weight:bold">会员登录</td> </tr> <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"><span class="error">${error}</span></td> </tr> <tr> <td colspan="2" align="center"><input type="submit" value="登入"></td> </tr> <tr> <td align="center"><a href="registerPage">注册</a></td> <td align="center"><a href="forgotPage">忘记密码?</a></td> </tr> </table> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> </form> </div> <div> <h1>简微</h1> <ul> <li>说你想说</li> <li>看你想看</li> <li>就这么简单</li> </ul> </div></body></html>删除了之前用Spring标签库做的内容,表单发送POST请求到login,这里千万注意,我们拦截规则的formPage中的/login是GET请求,会发送到我们的SecurityController处理,然后返回login.jsp视图,而视图表单中的login是POST给Spring Security处理的,会完成及鉴权相关的工作。另外,编单中添加了一个
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>这个是防止CSRF攻击的,Spring Security要求要有这个表单域。这样,如果我们输入的用户名密码与数据源比较通过校验,就会进入"/"请求,我们在HomeController中处理该请求
package com.yjp.springmvc.blog.web.controller;import org.springframework.security.core.context.SecurityContextHolder;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;@Controllerpublic class HomeController {@RequestMapping(method=RequestMethod.GET, value="/")public String home(Model model) {//通过Spring Security获取当前的用户UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext() .getAuthentication() .getPrincipal();model.addAttribute("username", userDetails.getUsername());return "home";}}该请求会跳转到home.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ page isELIgnored="false"%><!DOCTYPE html"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>简微</title><link rel="stylesheet" href="resources/css/home.css" type="text/css"></head><body><div class="leftPanel"><img src="resources/images/logo.png" alt="简微" /><br><br><form method="post" action="logout" style=""><input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/><button type="submit">注销 ${username}</button></form></div><form method="post" action="message">说说你的事...<br><br> <textarea cols='60' rows='4' name='blabla'></textarea><br><br><button type="submit">送出</button></form></body></html>这里的home.jsp我们已经完成了注销功能,注意有一个发送POST logout请求的表单,这个同样的道理,注销流程会交给Spring Security处理,主要是清除及鉴权相关的数据。
最后,由于我们要给鉴权提供数据源,持久层做了相应的改动,首先看看UserService
package com.yjp.springmvc.blog.beans.service;import org.springframework.security.core.userdetails.UserDetailsService;import com.yjp.springmvc.blog.beans.model.User;public interface UserService extends UserDetailsService {boolean saveUser(User user);}
package com.yjp.springmvc.blog.beans.service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.core.userdetails.UsernameNotFoundException;import org.springframework.stereotype.Service;import com.yjp.springmvc.blog.beans.model.User;import com.yjp.springmvc.blog.beans.repository.UserRepository;@Servicepublic class UserServiceImpl implements UserService {@Autowiredprivate UserRepository userRepository;@Overridepublic boolean saveUser(User user) {User saveUser = userRepository.save(user);return saveUser != null;}@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {UserDetails findUser = userRepository.findUserByUsername(username);if (findUser != null) {return findUser;} else {return null;}}}UserService实现了UserDetailsService接口,用来提供数据源,我们的数据源就是User对象,但是User对象实现了UserDetails接口
package com.yjp.springmvc.blog.beans.model;import java.io.Serializable;import java.util.Arrays;import java.util.Collection;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.Id;import javax.persistence.Table;import org.hibernate.annotations.GenericGenerator;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.authority.SimpleGrantedAuthority;import org.springframework.security.core.userdetails.UserDetails;@Entity@Table(name="users")public class User implements Serializable, UserDetails {private static final long serialVersionUID = 9038460243059691075L;@Id@GenericGenerator(strategy = "assigned", name = "username")private String username;@Columnprivate String password;@Columnprivate String email;public User() {}public User(String username, String password, String email) {this.username = username;this.password = password;this.email = email;}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;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {//返回用户权限return Arrays.asList(new SimpleGrantedAuthority("USER"));}@Overridepublic boolean isAccountNonExpired() {//账户是否会过期return true;}@Overridepublic boolean isAccountNonLocked() {//用户是否被锁定return true;}@Overridepublic boolean isCredentialsNonExpired() {//密码是否会过期return true;}@Overridepublic boolean isEnabled() {//用户是否使能return true;}}UserDetails接口的方法已经添加注释,可以酌情修改。这样就完成了Spring Security的配置,并将其使用在了我们的项目中。
0 0
- Spring学习之旅(八) Spring Security的使用
- spring security使用学习
- Spring Security的使用
- spring security的使用
- Spring security 学习使用笔记
- spring security学习,使用过程
- Spring学习笔记之Spring Security
- Spring Security中<@security.authorize的使用
- spring security的简单使用
- Spring Security的配置使用
- Spring Security学习记录(二) -- Spring Security的Filter
- Spring Security 2学习之登出
- Spring Security 2 学习之登录
- Spring Security oAuth学习之Hello World
- Spring Security 学习之X.509认证
- web项目学习之spring-security
- Spring Security学习笔记之整体配置
- Spring Security学习笔记之LogoutFilter
- ORA-39127: unexpected error from call to "WMSYS"."LT_EXPORT_PKG"."SCHEMA_INFO_EXP"
- 第7章 sed、gawk介绍与正则表达式-----------(sed编辑器简单使用)
- Hadoop到底是什么?
- Leetcode 333. Largest BST Subtree (Medium) (cpp)
- 10分钟教会你Mac上搭建Web服务器
- Spring学习之旅(八) Spring Security的使用
- java中设计模式-Strategy(策略模式)
- 个别操作需要有相应的声音提醒,
- Linux 下安装PHP+Apache+Mysql 手记
- 你们怎么看?"网站运营"
- shell脚本操作mysql
- HTML5移动端手机网站开发流程
- 关于iOS的重定向
- 如何提供一个短链(URL shorter)生成服务