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. 【JavaScript学习笔记】函数、数组、日期

    一.函数 一个函数应该只返回一种类型的值. 函数中有一个默认的数组变量arguments,存储着传入函数的所有参数. 为了使用函数参数方便,建议给参数起个名字. function fun1(obj, ...

  2. Mysql中使用mysqldump进行导入导出sql文件

    纪念工作中的第一次删库跑路的经历 今天接到一个任务,是将一个测试库数据导到另一个测试库,然而我们公司的数据库是不让直连的,所以只能通过远程连接进行导库操作. 老大布置任务的时候让用dump命令进行操作 ...

  3. Scala实践3

    一.函数式对象 1.1  rational类的规格和创建 Rational类来源于有理数(rational number),来表示n(分子)/d(分母)的数字,同时对有理数的运算(加减乘除)建模,还具 ...

  4. Prometheus+Alertmanager+Grafana监控组件容器部署

    直接上部署配置文件 docker-compose.yml version: '3' networks: monitor: driver: bridge services: prometheus: im ...

  5. cogs 182. [USACO Jan07] 均衡队形 线段树

    182. [USACO Jan07] 均衡队形 ★★☆   输入文件:lineup.in   输出文件:lineup.out   简单对比时间限制:4 s   内存限制:128 MB 题目描述 农夫约 ...

  6. cogs 1583. [POJ 3237] 树的维护 树链剖分套线段树

    1583. [POJ 3237] 树的维护 ★★★★   输入文件:maintaintree.in   输出文件:maintaintree.out   简单对比时间限制:5 s   内存限制:128 ...

  7. 2018 Multi-University Training Contest 10

      Recently, TeaTree acquire new knoledge gcd (Greatest Common Divisor), now she want to test you. As ...

  8. 20190925Java课堂记录(二)

    1. testrandom public class test2{ public static void main(String[] args) { int[] n=new int [1001]; n ...

  9. sqlalchemy 单表增删改查

    1.连接数据库,并创建session from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine engi ...

  10. HBase的安装、配置与实践

    本教程运行环境是在Ubuntu-64位系统下,HBase版本为hbase-1.1.2,这是目前已经发行的已经编译好的稳定的版本,带有src的文件是未编译的版本,这里我们只要下载bin版本hbase-1 ...