SpringSecurity

  SpringSecurity融合Spring技术栈,提供JavaEE应用的整体安全解决方案;提供全面的安全服务。Spring Security支持广泛的认证模型

模块划分

Core - spring-security-core.jar

核心模块:核心认证、授权功能、支持jdbc-user功能、支持独立的Spring应用

Remoting - spring-security-remoting.jar

远程交互模块:一般不需要,可以使用Spring Remoting功能简化远程客户端交互

Web - spring-security-web.jar

web安全模块:web项目使用,基于URL的访问控制(access-control)

Config - spring-security-config.jar

java配置模块:必须依赖包,包含解析xml方式和java 注解方式来使用SpringSecurity功能

LDAP - spring-security-ldap.jar

ldap(轻量目录访问协议)支持模块:可选依赖包,LDAP功能支持

ACL - spring-security-acl.jar

ACL支持:ACL(Access-Control-List)访问控制列表。细粒度的资源访问控制(RBAC+ACL)

CAS - spring-security-cas.jar

CAS整合支持:CAS(Central Authentication Service)中央认证服务。开源ApereoCAS整合

OpenID - spring-security-openid.jar

OpenID 认证方式: 用于针对外部服务器对用户进行身份验证(微信,新浪微博第三方登录)

Test - spring-security-test.jar

测试模块:快速的测试SpringSecurity应用

基于Maven Web工程实例

  添加 security-pom 依赖

    <!-- 安全框架中的jar包 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.2.10.RELEASE</version>
</dependency>
<!-- 标签库 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>4.2.10.RELEASE</version>
</dependency>

  web.xml 中添加 SpringSecurity的 Filter 进行安全控制

  <!-- 核心控制器,注意需将spring及springmvc配置文件都由Web容器装载 -->
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:/spring/springmvc.xml
classpath*:/spring/spring-*.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!--代理管理所有 SpringSecurity 过滤器-->
<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>

  SpringSecurity 配置类

/**
* @Configuration 管理程序中的组件(扫描)
* @EnableWebSecurity 安全框架支持注解的形式 基础注解
* @EnableGlobalMethodSecurity 开启使用表达式方法验证安全性
*/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AppWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override //认证
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
}
@Override //授权
protected void configure(HttpSecurity http) throws Exception {
}
}

  查看登录页面的源码,有个标签<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> 这是SpringSecurity 帮我们防止“跨站请求伪造”攻击;还可以防止表单重复提交。此标签 value 值会动态生成一个令牌值当用户请求登录时会验证此令牌值的正确性。如果想禁用此功能可在配置类中设置 http.csrf().disable();

l  令牌值变化:

如果登录成功(用户名,密码正确),令牌会被删除,

重新回到登录页或后退网页,令牌会重新生成;

如果登录失败(用户名,密码错误),令牌不变。

刷新登录页,令牌值也不变

认证

    @Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//从数据库中查询数据
  auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}

UserDetailsService

  此接口由 Security 来调用基于 AOP 模式进行权限检查,返回一个 UserDetails 接口类型其存放着该用户从数据库查询出来的所有权限信息

步骤:
  1 在业务层实现 UserDetailsService 接口通过用户名从 Dao 层查询出该用户对象
  2 创建一个 HashSet<GrantedAuthority> 接口类型的集合,该 GrantedAuthority 类型用来存放角色和权限信息,它的实现类 SimpleGrantedAuthority 需要传入字符串类型角色名和权限名
  3 通过该用户 id 查询出该用户所拥有的角色集合
  4 通过该用户 id 查询出该用户所拥有的权限集合
  5 通过所有角色名和所有权限名 创建 SimpleGrantedAuthority 对象并添加到 HashSet<GrantedAuthority> 集合中
  6 创建 User 类对象,该对象实现了 UserDetails 接口,为此 user 对象传入该用户的用户名和密码加上权限集合 Set 并返回该对象即可
    @Autowired //用户
private TAdminMapper adminMapper;
@Autowired //角色
private TRoleMapper roleMapper;
@Autowired //权限
private TPermissionMapper permissionMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
TAdminExample example = new TAdminExample();
TAdminExample.Criteria criteria = example.createCriteria();
criteria.andLoginacctEqualTo(username);
List<TAdmin> admins = adminMapper.selectByExample(example);
//从数据库中查出该用户
TAdmin admin = admins.get(0);
//该集合用来存放角色和权限
HashSet<GrantedAuthority> authorities = new HashSet<>();
//从数据库中查出该用户所对应的角色
List<TRole> roles = roleMapper.listRole(admin.getId());
//从数据库中查出该用户所对应的权限
List<TPermission> permissions = permissionMapper.listPermission(admin.getId());
//分别将角色和权限添加到 authorities 集合中
for (TRole role : roles) {
String name = role.getName();
authorities.add(new SimpleGrantedAuthority("ROLE_" + name));//注意角色需加上 "ROLE_"
}
permissions.forEach((p) -> {
String name = p.getName();
authorities.add(new SimpleGrantedAuthority(name));
});
//通过该用户名和密码以及权限集合创建User对象并返回
User user = new User(admin.getLoginacct().toString(), admin.getUserpswd().toString(), authorities);
return user;
}

授权

HttpSecurity 该类允许对特定的http请求基于安全考虑进行配置。默认情况下,适用于所有的请求.亦通过该对象 http 方法为用户配置精细化权限访问控制

    @Override
protected void configure(HttpSecurity http) throws Exception {
//基于httpRequest对指定antMatchers资源permitAll放行,对于其他请求anyRequest必须通过认证authenticated
http.authorizeRequests().antMatchers("/welcome.jsp","/static/**")
.permitAll().anyRequest().authenticated();
//跳转到默认登录界面
http.formLogin().loginPage("/welcome.jsp");
//登录时指定的控制器/login,并验证用户名和密码,成功验证后跳转到控制器/main
http.formLogin().loginProcessingUrl("/login")
.usernameParameter("loginacct")
.passwordParameter("userpswd")
.defaultSuccessUrl("/main");
//取消csrf令牌值验证
http.csrf().disable();
//退出时指定的控制器,并指定成功退出后登录界面
http.logout().logoutUrl("/exit").logoutSuccessUrl("/welcome.jsp");
//记住我功能.需在前端复选框中指定 value 值为 remember-me
http.rememberMe();
//自定义的异常处理器
http.exceptionHandling().accessDeniedHandler(new AccessDeniedHandler() {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
//判断是否为异步请求
if("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))){
response.getWriter().write("403");
}else {
request.setAttribute("msg",accessDeniedException.getMessage());
request.getRequestDispatcher("/WEB-INF/views/unauth.jsp")
.forward(request,response);
}
}
});
}

  通过方法调用可以更精细化控制访问权限   

    authorizeRequests():返回一个配置对象用于配置请求的访问限制
    formLogin():返回表单配置对象,当什么都不指定时会提供一个默认的,如配置登录请求,还有登录成功页面
    logout():返回登出配置对象,可通过logoutUrl设置退出url
    antMatchers:匹配请求路径或请求动作类型,如:.antMatchers("/admin/**")
    addFilterBefore: 在某过滤器之前添加 filter
    addFilterAfter:在某过滤器之后添加 filter
    addFilterAt:在某过滤器相同位置添加 filter,不会覆盖相同位置的 filter
    hasRole:结合 antMatchers 一起使用,设置请求允许访问的角色权限或IP

方法名

用途

access(String)

SpringEL表达式结果为true时可访问

anonymous()

匿名可访问

denyAll()

用户不可以访问

fullyAuthenticated()

用户完全认证访问(非remember me下自动登录)

hasAnyAuthority(String…)

参数中任意权限可访问

hasAnyRole(String…)

参数中任意角色可访问

hasAuthority(String)

某一权限的用户可访问

hasRole(String)

某一角色的用户可访问

permitAll()

所有用户可访问

rememberMe()

允许通过remember me登录的用户访问

authenticated()

用户登录后可访问

hasIpAddress(String)

用户来自参数中的IP可访问

@EnableGlobalMethodSecurity详解

    @EnableGlobalMethodSecurity(securedEnabled=true) 开启@Secured 注解过滤权限

      @Secured("软件工程师") :拥有指定角色才可以访问方法

    @EnableGlobalMethodSecurity(jsr250Enabled=true)开启@RolesAllowed 注解过滤权限

    @EnableGlobalMethodSecurity(prePostEnabled=true) 使用 SpEL 表达式方法级别的安全性         4个注解可用

@PreAuthorize 在方法执行之前检查,基于表达式的计算结果来限制对方法的访问   //@PreAuthorize("hasRole('软件工程师')")

@PostAuthorize 在方法执行后检查,但是如果表达式计算结果为false,将抛出一个安全性异常

@PostFilter 允许方法调用,但必须按照表达式来过滤方法的结果

@PreFilter 允许方法调用,但必须在进入方法之前过滤输入值

Security 标签

  在 jsp 页面还可通过标签进一步控制 html 标签的访问权限或获取该用户信息 : 引入标签库

<%@taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
 <sec:authentication property="name"/> //在需要位置显示用户登录名, 属性 property 必须是 name
<sec:authorize access="hasRole('PM - 项目经理')">//非此角色用户隐藏下面的标签
<button type="button" id="deleteBath" class="btn btn-danger" style="float:right;margin-left:10px;">删除</button>
</sec:authorize>

Java框架之SpringSecurity-权限系统的更多相关文章

  1. python的Web框架,auth权限系统

    使用django默认权限系统实现用户登录退出 判断用户是否登录 request.user.is_authenticated 返回的为bool值 一个简单的登录视图范式: # 导包 from djang ...

  2. 基于SpringBoot+SpringSecurity+mybatis+layui实现的一款权限系统

    这是一款适合初学者学习权限以及springBoot开发,mybatis综合操作的后台权限管理系统 其中设计到的数据查询有一对一,一对多,多对多,联合分步查询,充分利用mybatis的强大实现各种操作, ...

  3. SpringSecurity权限管理系统实战—六、SpringSecurity整合jwt

    目录 SpringSecurity权限管理系统实战-一.项目简介和开发环境准备 SpringSecurity权限管理系统实战-二.日志.接口文档等实现 SpringSecurity权限管理系统实战-三 ...

  4. 常见JAVA框架

     Spring Framework [Java开源JEE框架] Spring是一个解决了许多在J2EE开发中常见的问题的强大框架. Spring提供了管理业务对象的一致方法并且鼓励了注入对接口编程而不 ...

  5. S2SH商用后台权限系统第一讲

    各位博友: 您好!从今天开始我们做一套商用的权限系统.功能包含用户管理.角色管理.模块管理.权限管理.大家知道每个商用系统肯定会拥有一套后台系统,我们所讲的权限系统是整个系统核心部分.本套系统技术有s ...

  6. 高校手机签到系统——第一部分Authority权限系统(上)

    序:今天开始写一个算是我第一个系列的文章——高校手机签到系统.本系统结合我们学校自身的一些特点编写.这是我的毕业设计项目,写在这里算是给最后论文的时候一些点滴的记录.另外也想通过这个系列的文章找到一份 ...

  7. Spring Security和 JWT两大利器来打造一个简易的权限系统。

    写在前面 关于 Spring Security Web系统的认证和权限模块也算是一个系统的基础设施了,几乎任何的互联网服务都会涉及到这方面的要求.在Java EE领域,成熟的安全框架解决方案一般有 A ...

  8. Shiro整合springboot,freemaker,redis(含权限系统完整源码)

    区块链技术联盟 2018-02-08 17:06:40 目录 一.导语 二.shiro功能介绍 三.shiro详解 四.shiro实战案例分享 五.系统配置 六.其他 一.导语 今天推荐给大家一个非常 ...

  9. 转 分享我在阿里工作十年接触过Java框架设计模式

    转 原文: 分享我在阿里工作十年接触过Java框架设计模式 一.前言 说起来设计模式,大家应该都耳熟能详,设计模式代表了软件设计的最佳实践,是经过不断总结提炼出来的代码设计经验的分类总结,这些模式或者 ...

随机推荐

  1. 简单快速破解IDEA

    ====================================2019.09.16更新==================================== 可以直接去掉第三步,直接在激活 ...

  2. C语言之枚举数据类型

    枚举数据类型概述:1.枚举类型是C语言的一种构造类型.它用于声明一组命名的常数,2.当一个变量有几种可能的取值时,可以将它定义为枚举类型.3.枚举类型是由用户自定义的由多个命名枚举常量构成的类型,其声 ...

  3. 哪些工具可以提升PHP开发效率

    本文就我自己在开发过程中的一点经验,谈谈如何利用工具来提升开发工作的编码效率, IDE(phpstorm 收费) 一个好的IDE真的可以给开发人员节省大量的时间,我从最开始使用editplus 到su ...

  4. Friday the Thirteenth 黑色星期五 USACO 模拟 超级简单做法

    1003: 1.1.3 Friday the Thirteenth 黑色星期五 时间限制: 1 Sec  内存限制: 128 MB提交: 8  解决: 8[提交] [状态] [讨论版] [命题人:外部 ...

  5. Activiti工作流引擎开发系列

    Activiti工作流引擎开发系列-01 作者:Jesai 没有伞的孩子,只能光脚奔跑! 前言: 初次接触工作流这个概念是自从2014年11月份开始,当时是由于我的毕业设计需要,还记得当时我毕业设计的 ...

  6. ORM 效率补充

    1.only  defer only: 获取数据表中某列或多列的值,注意获取的是对象,如果查询字段不是括号内的,效率反而变低 defer: 获取除了某列或某几列的数据,注意获取的是对象 User.ob ...

  7. 系列免费课程汇总(Java、单体应用、微服务、物联网、SaaS)

    概述 2020年春节尽在眼前,又忙碌了一年的你一定有很多收获:是升职加薪,还是收获爱情?是买房置业,还是新添人口? 我在2019年的最大收获是:我的第二枚千金诞生,使我顺利加入富豪行列! 新年伊始我们 ...

  8. [bzoj3244] [洛谷P1232] [Noi2013] 树的计数

    Description 我们知道一棵有根树可以进行深度优先遍历(DFS)以及广度优先遍历(BFS)来生成这棵树的DFS序以及BFS序.两棵不同的树的DFS序有可能相同,并且它们的BFS序也有可能相同, ...

  9. 虚拟环境vitualenv的使用

    在使用 Python 开发的过程中,工程一多,难免会碰到不同的工程依赖不同版本的库的问题: 亦或者是在开发过程中不想让物理环境里充斥各种各样的库,引发未来的依赖灾难. 此时,我们需要对于不同的工程使用 ...

  10. mysql 记录一次内存清理

    摘自:https://blog.csdn.net/wyzxg/article/details/7279986/ 摘要:Linux对内存的管理与Windows不同,free小并不是说内存不够用了,应该看 ...