Spring Boot框架我们前面已经介绍了很多了,相信看了前面的博客的小伙伴对Spring Boot应该有一个大致的了解了吧,如果有小伙伴对Spring Boot尚不熟悉,可以先移步这里从SpringMVC到Spring Boot,老司机请略过。OK,那我们今天要说的是Spring Boot中另外一个比较重要的东西,那就是Spring Security,这是一个专门针对基于Spring的项目的安全框架,它主要是利用了我们前文介绍过的的AOP(Spring基础配置)来实现的。以前在Spring框架中使用Spring Security需要我们进行大量的XML配置,但是,Spring Boot在这里依然有惊喜带给我们,我们今天就一起来看看。 
毫无疑问,Spring Boot针对Spring Security也提供了自动配置的功能,这些默认的自动配置极大的简化了我们的开发工作,我们今天就来看看这个吧。

创建Project并添加相关依赖

Project的创建和前文一样,唯一要注意的地方就是创建的时候添加的依赖不同,如下图: 
 
OK,创建成功之后添加相关依赖,数据库我这里使用MySql,所以添加MySql驱动,然后要添加Spring Security的支持,所以还要添加Spring Security的依赖,如下:

<dependency><groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity4</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.40</version> </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

配置application.properties

这个东东的配置还是和我们上文说到的是一样的,这里也没啥好说的,有问题的小伙伴翻看前文(初识在Spring Boot中使用JPA):

spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/sang?useUnicode=true&characterEncoding=utf-8 spring.datasource.username=root spring.datasource.password=sang logging.level.org.springframework.security=info spring.thymeleaf.cache=false spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

定义用户和角色

我们这里使用JPA来定义用户和角色,用户和角色都存储在数据库中,我们直接通过在数据库中查询然后来使用。

定义角色

我们的角色实体类和表都很简单,就两个字段,一个id,一个name属性表示角色的名称,实体类如下;

@Entity
public class SysRole { @Id @GeneratedValue private Long id; private String name; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }

OK,简简单单就这两个属性。

定义用户

我们在定义用户的时候需要实现UserDetails接口,这样我们的用户实体即为Spring Security所使用的用户,定义好用户之后,我们还要配置用户和角色之间的多对多关系,正常情况下,角色和权限是两回事,所以我们还需要重写getAuthorities方法,将用户的角色和权限关联起来,代码如下:

@Entity
public class SysUser implements UserDetails { @Id @GeneratedValue private Long id; private String username; private String password; @ManyToMany(cascade = {CascadeType.REFRESH},fetch = FetchType.EAGER) private List<SysRole> roles; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } public List<SysRole> getRoles() { return roles; } public void setRoles(List<SysRole> roles) { this.roles = roles; } @Override public Collection<? extends GrantedAuthority> getAuthorities() { List<GrantedAuthority> auths = new ArrayList<>(); List<SysRole> roles = this.getRoles(); for (SysRole role : roles) { auths.add(new SimpleGrantedAuthority(role.getName())); } return auths; } @Override public String getPassword() { return this.password; } @Override public String getUsername() { return this.username; } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } } 

OK,经过上面两个步骤之后我们的用户就和角色关联起来了,这个时候运行Project就会在数据库中自动帮我们生成三张表,用户表、角色表和两者的关联表,如下: 

预设数据

我们先在表中定义好几个角色和用户,方便我们后边做测试用,OK,预设数据的话,那我们执行如下几行数据插入代码:

insert  into `sys_role`(`id`,`name`) values (1,'ROLE_ADMIN'),(2,'ROLE_USER'); insert into `sys_user`(`id`,`password`,`username`) values (1,'root','root'),(2,'sang','sang'); insert into `sys_user_roles`(`sys_user_id`,`roles_id`) values (1,1),(2,2); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

我们向数据库中插入两个用户两个角色,再将这两个用户两个角色关联起来即可。

创建传值对象

数据创建成功之后,在客户端请求网页的时候我们需要有一个实体类用来向客户端传递消息,OK,那我们创建一个MSG对象:

public class Msg {private String title;private String content;private String extraInfo; public Msg() { } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getExtraInfo() { return extraInfo; } public void setExtraInfo(String extraInfo) { this.extraInfo = extraInfo; } public Msg(String title, String content, String extraInfo) { this.title = title; this.content = content; this.extraInfo = extraInfo; } }

这就是一个普通的类,没什么好说的。

创建数据访问接口

public interface SysUserRepository extends JpaRepository<SysUser, Long> { SysUser findByUsername(String username); }

这个也是写了n多遍的东西了,不赘述,关于这里如果小伙伴有疑问可以参考这里(初识在Spring Boot中使用JPA)。需要注意的是这里只需要一个根据用户名查询出用户的方法即可,不需要通过用户名和密码去查询。

自定义UserDetailsService

自定义UserDetailsService,实现相应的接口,如下:

public class CustomUserService implements UserDetailsService { @Autowired SysUserRepository userRepository; @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { SysUser user = userRepository.findByUsername(s); if (user == null) { throw new UsernameNotFoundException("用户名不存在"); } System.out.println("s:"+s); System.out.println("username:"+user.getUsername()+";password:"+user.getPassword()); return user; } }

首先这里我们需要重写UserDetailsService接口,然后实现该接口中的loadUserByUsername方法,通过该方法查询到对应的用户,这里之所以要实现UserDetailsService接口,是因为在Spring Security中我们配置相关参数需要UserDetailsService类型的数据。

SpringMVC配置

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/login").setViewName("login"); } }

当用户访问login时跳转到login.html页面。

配置Spring Security

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Bean UserDetailsService customUserService() { return new CustomUserService(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(customUserService()); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() .and().formLogin().loginPage("/login").failureUrl("/login?error").permitAll().and() .logout().permitAll(); } }

OK ,关于这个配置我要多说两句:

1.首先当我们要自定义Spring Security的时候我们需要继承自WebSecurityConfigurerAdapter来完成,相关配置重写对应 方法即可。 
2.我们在这里注册CustomUserService的Bean,然后通过重写configure方法添加我们自定义的认证方式。 
3.在configure(HttpSecurity http)方法中,我们设置了登录页面,而且登录页面任何人都可以访问,然后设置了登录失败地址,也设置了注销请求,注销请求也是任何人都可以访问的。 
4.permitAll表示该请求任何人都可以访问,.anyRequest().authenticated(),表示其他的请求都必须要有权限认证。 
5.这里我们可以通过匹配器来匹配路径,比如antMatchers方法,假设我要管理员才可以访问admin文件夹下的内容,我可以这样来写:.antMatchers("/admin/**").hasRole("ROLE_ADMIN"),也可以设置admin文件夹下的文件可以有多个角色来访问,写法如下:.antMatchers("/admin/**").hasAnyRole("ROLE_ADMIN","ROLE_USER") 
6.可以通过hasIpAddress来指定某一个ip可以访问该资源,假设只允许访问ip为210.210.210.210的请求获取admin下的资源,写法如下.antMatchers("/admin/**").hasIpAddress("210.210.210.210") 
7.更多的权限控制方式参看下表: 

8.这里我们还可以做更多的配置,参考如下代码:

http.authorizeRequests().anyRequest().authenticated().and().formLogin().loginPage("/login") //设置默认登录成功跳转页面 .defaultSuccessUrl("/index").failureUrl("/login?error").permitAll() .and() //开启cookie保存用户数据 .rememberMe() //设置cookie有效期 .tokenValiditySeconds(60 * 60 * 24 * 7) //设置cookie的私钥 .key("") .and() .logout() //默认注销行为为logout,可以通过下面的方式来修改 .logoutUrl("/custom-logout") //设置注销成功后跳转页面,默认是跳转到登录页面 .logoutSuccessUrl("") .permitAll();

OK,这里算是核心了,多说两句。

创建登录页面

在template文件夹中创建login.html页面,内容如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"/> <title>登录</title> <link rel="stylesheet" th:href="@{css/bootstrap.min.css}"/> <link rel="stylesheet" th:href="@{css/signin.css}"/> <style type="text/css"> body { padding-top: 50px; } .starter-template { padding: 40px 15px; text-align: center; } </style> </head> <body> <nav class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <a class="navbar-brand" href="#">Spring Security演示</a> </div> <div id="navbar" class="collapse navbar-collapse"> <ul class="nav navbar-nav"> <li><a th:href="@{/}">首页</a></li> <li><a th:href="@{http://www.baidu.com}">百度</a></li> </ul> </div> </div> </nav> <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 class="form-signin" role="form" name="form" th:action="@{/login}" 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" value="Login" class="btn btn-primary"/> </form> </div> </div> </body> </html>

这里就是一个普通的html页面,用到了thymeleaf模板引擎(thymeleaf可以参考这两篇文章使用Spring Boot开发Web项目/使用Spring Boot开发Web项目(二)之添加HTTPS支持),

创建登录成功后跳转页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"> <head> <meta charset="UTF-8"/> <title sec:authentication="name"></title> <link rel="stylesheet" th:href="@{css/bootstrap.min.css}"/> <style type="text/css"> body { padding-top: 50px; } .starter-template { padding: 40px 15px; text-align: center; } </style> </head> <body> <nav class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <a class="navbar-brand" href="#">Spring Security演示</a> </div> <div id="navbar" class="collapse navbar-collapse"> <ul class="nav navbar-nav"> <li><a th:href="@{/}">首页</a></li> <li><a th:href="@{http://www.baidu.com}">百度</a></li> </ul> </div> </div> </nav> <div class="container"> <div class="starter-template"> <h1 th:text="${msg.title}"></h1> <p class="bg-primary" th:text="${msg.content}"></p> <div sec:authorize="hasRole('ROLE_ADMIN')"> <p class="bg-info" th:text="${msg.extraInfo}"></p> </div> <div sec:authorize="hasRole('ROLE_USER')"> <p class="bg-info">无更多显示信息</p> </div> <form th:action="@{/logout}" method="post"> <input type="submit" class="btn btn-primary" value="注销"/> </form> </div> </div> </body> </html>

这里有如下几个问题需要说明:

1.在html标签中我们引入的Spring Security 
2.通过sec:authentication=”name”我们可以获取当前用户名 
3.sec:authorize="hasRole('ROLE_ADMIN')表示当前用户角色为ROLE_ADMIN的话显示里边的内容 
4.sec:authorize="hasRole('ROLE_USER')表示当前用户角色为ROLE_USER的话显示该DIV里边的内容

添加控制器

@Controller
public class HomeController { @RequestMapping("/") public String index(Model model) { Msg msg = new Msg("测试标题", "测试内容", "额外信息,只对管理员显示"); model.addAttribute("msg", msg); return "index"; } }

测试

首页如下:

访问http://localhost:8080/自动跳转到http://localhost:8080/login 

登录出错

输入错误的账号密码进行登录,结果如下: 

管理员登录

使用管理员帐号密码登录,结果如下: 

普通用户登录

使用普通用户帐号密码登录,结果如下: 

注销

点击注销按钮,结果如下: 

OK,以上就是对Spring Security的一个简单介绍,是不是比自己通过过滤器、拦截器神马的来弄简单多了。

转载于:https://www.cnblogs.com/jiadp/p/9288573.html

在Spring Boot中使用Spring Security实现权限控制相关推荐

  1. Spring boot中使用Spring Security的记住我 remember-me功能

    Spring boot中使用Spring Security的记住我 remember-me功能 问题描述:Spring security新手,在登录时加上记住我功能,需要使用框架自带的记住我. 记住的 ...

  2. Spring Boot中使用Spring Security进行安全控制

    我们在编写Web应用时,经常需要对页面做一些安全控制,比如:对于没有访问权限的用户需要转到登录表单页面.要实现访问控制的方法多种多样,可以通过Aop.拦截器实现,也可以通过框架实现(如:Apache ...

  3. java 方式配置ssm,关于SSM以及Spring boot中对于Spring MVC配置的问题

    SSM中 Spring MVC配置 传统的web.xml配置 web.xml contextConfigLocation classpath*:applicationContext.xml org.s ...

  4. 在 Spring Boot 中使用 Spring AOP 和 AspectJ 来测量方法的执行时间

    原文链接:https://dzone.com/articles/logging-average-method-execution-times-via-aspectj 作者:Murat Derman 译 ...

  5. Spring Boot中使用Spring Data JPA示例

    JPA是Java Persistence API的简称,是sun公司早期推出的Java持久层规范,目前实现JPA规范的主流框架有Hibernate.OpenJPA等.Hibernate框架是当前较为流 ...

  6. Spring Boot 2.6之后,动态权限控制终于可以用起来了!

    Spring Security 5.6 发布有些时间了.随着Spring Boot 2.6的发布Spring Security 5.6终于有机会上生产了.在Spring Security 5.6中动态 ...

  7. spring boot中配置虚拟路径,用来映射显示图片

    增加配置,继承 WebMvcConfigurerAdapter,如下: package com.wm.mogu_picture.config;import org.springframework.be ...

  8. 在Spring Boot中加载初始化数据

    文章目录 依赖条件 data.sql文件 schema.sql 文件 @sql注解 @SqlConfig 注解 在Spring Boot中加载初始化数据 在Spring Boot中,Spring Bo ...

  9. 第 4-4 课:Spring Boot 中使⽤ Cache 缓存的使⽤

    我们知道绝⼤多数的⽹站/系统,最先遇到的⼀个性能瓶颈就是数据库,使⽤缓存做数据库的前置缓存,可以 ⾮常有效地降低数据库的压⼒,从⽽提升整个系统的响应效率和并发量. 以往使⽤缓存时,通常创建好缓存⼯具类 ...

  10. springboot 访问html_Spring Boot中使用Spring Security进行安全控制

    我们在编写Web应用时,经常需要对页面做一些安全控制,比如:对于没有访问权限的用户需要转到登录表单页面.要实现访问控制的方法多种多样,可以通过Aop.拦截器实现,也可以通过框架实现(如:Apache ...

最新文章

  1. andorid 开发笔记 -- 问题与解决
  2. 进程调度算法Java代码
  3. 夺命雷公狗---PHP开发APP接口---1(手动编写json)
  4. 剑指 Offer 44. 数字序列中某一位的数字
  5. Java常用设计模式————原型模式(二)之深拷贝与浅拷贝
  6. WebSocket实战
  7. 程序设计基础(C语言)课程设计报告,C语言程序设计基础课程设计报告.doc
  8. Android性能优化典范第一季
  9. try-catch语句
  10. renpy-视觉小说转换器-编程零基础写视觉小说
  11. 20行代码实现(UartLogger)串口监控记录器
  12. 关联本地项目和svn_技术贴 本地代码与svn关联教程 svn upgrade问题解决
  13. 刷新ListView刷新时的闪烁问题
  14. css loader.net,css-loader style-loader原理探究
  15. 软件-xyplorer
  16. ubuntu如何杀进程_ubuntu kill进程
  17. 视频号视频如何下载?
  18. ElementPlus 侧边栏右侧空隙
  19. Self-supervised Graph Learning for Recommendation
  20. 工行华虹U盾在Vista和IE7下的解决方案

热门文章

  1. python获取图片大小_Python实现获取本地及远程图片大小的方法示例_python_脚本中心...
  2. 华三 h3c VRRP、MSTP、OSPF综合实验
  3. 习惯性的对自己没信心,其实没想到自己已经变强大了。
  4. Java011-多线程
  5. [转载]敏捷开发,你真的做对了吗?
  6. 2013-06-18
  7. 快切-开源中文css框架之纯css透明
  8. SBCL 使用中文时的错误记录 --close 问题已经解决
  9. 技术帝出没:对做梦推的强力回复们
  10. ASP.NET面试题(推荐_有答案)