SpringBoot学习(六)SpringSecurity学习
来源:互联网 发布:淘宝网皮衣加厚的 编辑:程序博客网 时间:2024/06/11 15:49
SpringSecurity介绍
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
应用级别的安全主要分为“验证( authentication) ”和“(授权) authorization ”两个部分。这也是Spring Security主要需要处理的两个部分。“ Authentication ”指的是建立规则( principal )的过程。规则可以是一个用户、设备、或者其他可以在我们的应用中执行某种操作的其他系统。” Authorization “指的是判断某个 principal 在我们的应用是否允许执行某个操作。在 进行授权判断之前,要求其所要使用到的规则必须在验证过程中已经建立好了。
除了验证机制, Spring Security 也提供了一系列的授权能力。主要感兴趣的是以下三个方面:
- 对web请求进行授权
- 授权某个方法是否可以被调用
- 授权访问单个领域对象实例
关于SpringSecurity的学习主要是参考http://www.tianshouzhi.com/api/tutorials/spring_security_4/250,这里面还提供了对源码的解读,对于我这种渣渣来说,看起来还是有点费劲的
在Springsecurity中有两种配置方式,是xml文件配置和java配置,两者配置差别不打,个人感觉java配置使用起来比较方便,所以主要记录一下java配置的过程。
java基本配置
新建项目
新建一个SpringBoot项目,pom.xml中需要的包(勾选或者直接手写)
devtoolsthymeleafsecurity
在pom中添加这三个包之后,可以启动项目看看,访问项目下的任意一个路径都会被拦截要求输入用户名和密码,由于啥都还没有设置,所以用户名是user
,密码在启动springboot的时候在console输出了,类似f1ea0b2d-b053-40fd-abc5-065a4f45b266
这样的一串就是默认密码。
配置自己的用户名密码
在项目根目录下添加SecurityConfig.java
文件
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter{ @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER"); }}
然后访问任意一个URL都会跳转到下面这个界面
输入刚刚设置的用户名密码就可以重新跳转回所要访问的界面
这段代码内容很少,但事实上已经做了很多的默认安全验证,包括:
- 访问应用中的每个URL都需要进行验证
- 生成一个登陆表单
- 允许用户使用username和password来登陆
- 允许用户注销
- CSRF攻击拦截
- Session Fixation攻击
- 安全Header集成
配置自定义的登录界面
在SecurityConfig.java
中添加下面的代码,主要是说拦截所有请求,然后配置自定义的登陆界面的路径为“/login”
@Overrideprotected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage( "/login") .permitAll(); }
在templates文件夹下添加login.html文件,我这个html文件是从之前写的直接拷贝过来的。
<html xmlns:th="http://www.thymeleaf.org"><head><meta content="text/html;charset=utf-8" /><title>登录界面</title><style type="text/css">.starter-template { padding: 40px 15px; text-align: center;}</style></head><body> <div class="container"> <div class="starter-template"> <p th:if="${param.logout}" class="bg-warning">已成功注销</p> <p th:if="${param.error}" class="bg-danger">有错误,请重试</p> <h2>使用账号密码登陆</h2> <form name="form" th:action="@{/login}" method="POST"> <div class="form-group"> <label for="username">账号:</label> <input type="text" class="form-control" name="username" value="" placeholder="账号" /> </div> <div class="form-group"> <label for="password">密码:</label> <input type="password" class="form-control" name="password" placeholder="密码" /> </div> <input type="submit" id="login" class="btn btn-primary" /> </form> </div> </div></body></html>
然后在添加一个文件WebMvcConfig
,将“/login”映射到“login.html”
import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;@Configurationpublic class WebMvcConfig extends WebMvcConfigurerAdapter{ @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/login").setViewName("login"); }}
这个时候重新访问刚刚的路径,就会拦截到自定义的登录界面
这里Html文件中的用户名密码,默认的name属性名字是“username”和“password”,否则springsecurity是获取不到值的,如需要自定的话,可以这么设置
@Overrideprotected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage( "/login") .usernameParameter("username") .passwordParameter("password") .permitAll();}
退出登录
可以在configure函数下继续设置:
@Overrideprotected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage( "/login") .usernameParameter("username") .passwordParameter("password") .permitAll() .and() .logout() .logoutUrl("/logout") .logoutSuccessUrl("/index") .invalidateHttpSession(true) .permitAll();}
可以直接从代码中看出来,就是访问“/logout”的时候会退出登录,若成功退出便会访问到“/index”这个路径,这个比较简单,就不贴代码出来了,可以下载我的源码去看看。
拦截url和授权
之前设置的都是拦截全部的URL,不管什么URL都拦截到登录界面,也可以自定义拦截,同样是在configure函数下添加设置:
- resources路径下的文件和以show开头的路径无需登录结课访问
- test该URl只能由用户为ADMIN的访问
- index该路径可由ADMIN和USER_ADMIN的用户访问
@Overridepublic void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers( "/resources/**", "/show*").permitAll() .antMatchers( "/test").hasRole("ADMIN" ) .antMatchers( "/idnex").access("hasRole('ADMIN') and hasRole('USER_ADMIN')") .antMatchers( "/AddUser").access("hasRole('ADMIN') and hasRole('USER')") // .regexMatchers("").permitAll()正则表达式匹配 .anyRequest().authenticated() // .authorizeRequests()// .anyRequest().authenticated() .and() .formLogin() .loginPage( "/login") .usernameParameter("username") .passwordParameter("password") .permitAll() .and() .logout() .logoutUrl("/logout") .logoutSuccessUrl("/index") .invalidateHttpSession(true) .permitAll(); }
关于用户的权限,可在设置用户名和密码是指定
@Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("1").password("1").roles("ADMIN").and() .withUser("2").password("2").roles("USER").and() .withUser("3").password("3").roles("USER_ADMIN").and() .withUser("4").password("4").roles("USER"); }
配置mysql数据库中的用户名密码
关于数据库的而配置连接,参考我的上一篇博客http://blog.csdn.net/q15150676766/article/details/76795466,这里不做介绍。
我数据库中一张表SysUser(id,username,password,role)
在java中新建一个entity类SysUser.java
注意这个类需要实现UserDetails接口。数据库中的role字段需要有”ROLE_”作为前缀,或者需要在构建的时候拼接“ROLE_”,我这里是拼接的。
@Entitypublic class SysUser implements UserDetails{ /** * */ private static final long serialVersionUID = 1L; @Id @GeneratedValue private Long id; private String username; private String password; private String role; //getter....setter.... @Override public Collection<? extends GrantedAuthority> getAuthorities() { List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>(); auths.add(new SimpleGrantedAuthority("ROLE_"+role)); return auths; } @Override public boolean isAccountNonExpired() { // TODO Auto-generated method stub return true; } @Override public boolean isAccountNonLocked() { // TODO Auto-generated method stub return true; } @Override public boolean isCredentialsNonExpired() { // TODO Auto-generated method stub return true; } @Override public boolean isEnabled() { // TODO Auto-generated method stub return true; }}
新建一个JPA的类SysUserRepository.java
这个很简单就不做解释了。
import org.springframework.data.jpa.repository.JpaRepository;public interface SysUserRepository extends JpaRepository<SysUser, Long>{ SysUser findByUsername(String username);}
新建一个CustomUserService.java
文件
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.core.userdetails.UsernameNotFoundException;public class CustomUserService implements UserDetailsService { @Autowired SysUserRepository userRepository; @Override public UserDetails loadUserByUsername(String username) { SysUser user = userRepository.findByUsername(username); if (user == null) { throw new UsernameNotFoundException("用户不存在"); } return user; }}
最后在SecurityConfig.java
文件中添加
@Bean UserDetailsService customUserService(){ return new CustomUserService(); }
在configure方法下添加
auth.userDetailsService(customUserService());
这样就可以将数据库中的用户名密码添加到springsecurity中。
关于原理可以去参考一下http://www.tianshouzhi.com/api/tutorials/spring_security_4/250
测试这里便不做了,可以下载我的源码去试试看
- SpringBoot学习(六)SpringSecurity学习
- SpringSecurity源码学习(六)
- springsecurity学习(一)
- SpringSecurity学习(一)
- SpringSecurity学习笔记之六:保护视图
- SpringSecurity源码学习(一)
- SpringSecurity源码学习(二)
- SpringSecurity源码学习(三)
- SpringSecurity源码学习(五)
- SpringBoot学习-(六)SpringBoot与Mybatis整合
- SpringSecurity 学习记录(一)- SpringSecurity 主要的实现类
- SpringBoot 学习记录(六): Exception
- springboot学习笔记(六) Mybatis
- Spring+SpringSecurity 学习总结
- SpringSecurity学习笔记一
- springSecurity工作流程学习
- SpringBoot学习(六)——事务的管理
- Spring学习笔记-C9-SpringSecurity
- Ubuntu Install OpenCV 2.4.13 for QT Guide
- eclipse中利用Maven逆向工程生成PO类以及mapper(mybatis)
- Logistic 分类器与 softmax分类器
- js中几种实用的跨域方法原理详解
- 工类下载
- SpringBoot学习(六)SpringSecurity学习
- 日常纪要
- android中动态给EditText获得焦点并弹起软键盘的方法详解
- PHP类中static 和self的使用区别
- java JAXB注解
- 医学全面云转型大势已定
- Html中CSS之去除li前面的小黑点,和ul、LI部分属性方法
- Web开发之常见端口
- Pixhawk之姿态控制篇(1)_源码算法分析