Spring Security 整合freemaker 实现简单登录和角色控制

Stella981
• 阅读 189

Spring Security 整合freemaker 实现简单登录和角色控制

写这篇文章是因为我做了一个电商网站项目,近期刚加上权限控制。整个过程很简单,在此给大家梳理一下,也算是自己对知识点的一个总结。

一、需求分析:

我们都知道,电商网站在权限这一块,有两大块内容:

       1、用户未登录,部分页面拒绝访问(如:下订单)

       2、不同角色用户登录看到的功能模块不一样(如:买家、卖家、客服等)

基于以上需求,接下来我们要解决的就是对用户登录的拦截以及对权限和角色的控制。

二、项目环境说明:

使用SSM(SpringMVC+Spring+Mybatis)框架,mysql数据库、maven项目管理工具,freemaker前端引擎。对以上又不懂的朋友们可以自己去百度了解,这里就废话不多说了。

三、前期储备知识(如果对Spring Security很熟悉的可以跳过此步)

Security框架可以精确控制页面的一个按钮、链接,它在页面上权限的控制实际上是通过它提供的标签来做到的。

  • 简介

       一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方式的安全框架(简单说是对访问权限进行控制嘛),应用的安全性包括用户认证(Authentication)用户授权(Authorization)两个部分。用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。spring security的主要核心功能为认证和授权,所有的架构(如:Shiro安全框架)也是基于这两个核心功能去实现的。

  • 框架原理

     众所周知 想要对对Web资源进行保护,最好的办法莫过于Filter,要想对方法调用进行保护,最好的办法莫过于AOP。所以springSecurity在我们进行用户认证以及授予权限的时候,通过各种各样的拦截器来控制权限的访问,从而实现安全。

        如下为其主要过滤器  :

        WebAsyncManagerIntegrationFilter 
        SecurityContextPersistenceFilter 
        HeaderWriterFilter 
        CorsFilter 
        LogoutFilter
        RequestCacheAwareFilter
        SecurityContextHolderAwareRequestFilter
        AnonymousAuthenticationFilter
        SessionManagementFilter
        ExceptionTranslationFilter
        FilterSecurityInterceptor
        UsernamePasswordAuthenticationFilter
        BasicAuthenticationFilter

  • 框架的核心组件

      SecurityContextHolder:提供对SecurityContext的访问
      SecurityContext,:持有Authentication对象和其他可能需要的信息
      AuthenticationManager 其中可以包含多个AuthenticationProvider
      ProviderManager对象为AuthenticationManager接口的实现类
      AuthenticationProvider 主要用来进行认证操作的类 调用其中的authenticate()方法去进行认证操作
      Authentication:Spring Security方式的认证主体
     GrantedAuthority:对认证主题的应用层面的授权,含当前用户的权限信息,通常使用角色表示
     UserDetails:构建Authentication对象必须的信息,可以自定义,可能需要访问DB得到
     UserDetailsService:通过username构建UserDetails对象,通过loadUserByUsername根据userName获取UserDetail对象 

     以上知识点来源于博客:springSecurity安全框架的学习和原理解读

四、开始实战:

本文内容主要实现三部分内容:

1、控制不同角色只能访问网站中不同链接(与2作区分)

2、控制不同角色用户看到网站中不同的模块

3、对有权限控制的路径,控制用户session过期时重新跳转到登录页面

  • 在pom.xml文件中加入Security 坐标:
  1. org.springframework.security

  2. spring-security-core

  3. 3.2.0.RELEASE

  4. org.springframework.security

  5. spring-security-web

  6. 3.2.0.RELEASE

  7. org.springframework.security

  8. spring-security-config

  9. 3.2.0.RELEASE

  10. org.springframework.security

  11. spring-security-taglibs

  12. 3.2.0.RELEASE

  • 在web.xml中配置Security

 

  1. springSecurityFilterChain

  2. org.springframework.web.filter.DelegatingFilterProxy

  3. springSecurityFilterChain

  4. /*

  • Controller文件代码 (SecurityConfig.java)
  1. @Configuration

  2. @EnableWebSecurity

  3. @Component

  4. public class SecurityConfig extends WebSecurityConfigurerAdapter {

  5. @Autowired

  6. private UserDetailService userDetailService;

  7. @Override

  8. protected void configure(HttpSecurity http) throws Exception{

  9. http.authorizeRequests()

  10. .antMatchers( "/index/show").hasAnyRole("ADMIN","BUYER","SELLER")//个人首页只允许拥有ADMIN,BUYER,SELLER角色的用户访问

  11. .antMatchers( "/cart/show").hasAnyRole("ADMIN","MAIJIA","SELLER")

  12. //在此后面可以根据自己的项目需要进行页面拦截的添加

  13. .anyRequest().authenticated()

  14. .and()

  15. .formLogin()

  16. .loginPage( "/index/login").permitAll()//这里程序默认路径就是登陆页面,允许所有人进行登陆

  17. .loginProcessingUrl( "/j_spring_security_check")//登陆提交的处理url

  18. .usernameParameter( "j_username")//登陆用户名参数

  19. .passwordParameter( "j_password")//登陆密码参数

  20. .failureUrl( "/index/login?error=true")//登陆失败进行转发,这里回到登陆页面,参数error可以告知登陆状态

  21. .defaultSuccessUrl( "/index/show")//登陆成功的url,这里去到个人首页

  22. .and().logout().logoutUrl( "/j_spring_security_logout").permitAll().logoutSuccessUrl("/index/login?logout=true")//按顺序,第一个是登出的url,security会拦截这个url进行处理,所以登出不需要我们实现,第二个是登出url,logout告知登陆状态

  23. .and()

  24. .addFilter(myUsernamePasswordAuthenticationFilter)

  25. .rememberMe()

  26. .tokenValiditySeconds( 604800)//记住我功能,cookies有限期是一周

  27. .and()

  28. .csrf().disable();

  29. }

  30. @Override

  31. public void configure(WebSecurity web) throws Exception{

  32. super.configure(web);

  33. }

  34. @Override

  35. public void configure(AuthenticationManagerBuilder auth) throws Exception{

  36. auth.userDetailsService(userDetailService);

  37. }

  38. @Override

  39. public AuthenticationManager authenticationManagerBean() throws Exception {

  40. return super.authenticationManagerBean();

  41. }

  42. }

  • 接下来是Service层的代码(UserDetailService.java)
  1. @Service

  2. public class UserDetailService implements UserDetailsService {

  3. @Autowired

  4. private UserDetailsDao userDetailsDao;

  5. /**

  6. * 获取所属角色

  7. */

  8. public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

  9. //查出用户名、密码、角色信息

  10. Users users = userDetailsDao.getUserByName(username);

  11. if (users==null) {

  12. throw new UsernameNotFoundException("找不到该账户信息!");

  13. }

  14. List list = new ArrayList(); //GrantedAuthority是security提供的权限类,

  15. list.add( new SimpleGrantedAuthority("ROLE_"+users.getRoles()));

  16. User auth_user = new User(users.getUsername(), users.getPassword(), list);

  17. return auth_user;

  18. }

  19. }

  • 前端代码 .ftl文件(在此只粘出一部分代码,只显示一下用法)

       在ftl文件头部加上,引入Security文件

<#assign sec=JspTaglibs["http://www.springframework.org/security/tags"]/>
  1. <#--没有登录时 能看到买家、卖家所有信息-->

  2. < @sec.authorize ifNotGranted="ROLE_ADMIN,ROLE_MAIJIA,ROLE_SELLER,ROLE_BOTHSM">

  3. 买家中心
  4. 全部订单

  5. 优惠券

  6. 我的购物车

  7. 我的收藏

  8. 卖家中心
  9. 已卖出货品

  10. 发布供应产品

  11. 管理供应产品

  12. 发布公告

  13. </ @sec.authorize>

  14. <#--登陆后,买家中心 只有以买家身份登录可以看到-->

  15. < @sec.authorize ifAnyGranted="ROLE_MAIJIA">

  16. 买家中心
  17. 全部订单

  18. 优惠券

  19. 我的购物车

  20. 我的收藏

  21. </ @sec.authorize>

  22. <#--登陆后,卖家中心 只有以卖家身份登录可以看到-->

  23. < @sec.authorize ifAnyGranted="ROLE_SELLER">

  24. 卖家中心
  25. 已卖出货品

  26. 发布供应产品

  27. 管理供应产品

  28. 发布公告

  29. </ @sec.authorize>

五、附加知识点:

页面标签的使用与权限配置相对应

authorize标签判断顺序是: access->url->ifNotGranted->ifAllGranted->ifAnyGranted

但他们的关系是“与”: 即只要其中任何一个属性不满足则该标签中间的内容将不会显示给用户,举个例子:

<sec:authorize  ifAllGranted=”ROLE_ADMIN,ROLE_MEMBER” ifNotGranted=”ROLE_SUPER”>满足才会显示给用户

标签中间的内容只有在当前用户拥有ADMIN,MEMBER角色,但不拥有SUPER权限时才会显示!

access属性是基于角色判断,url属性是基于访问路径判断。

对于ifAllGranted ,ifNotGranted,ifAnyGranted属性的理解可以与集合api类比

Collection grantedAuths :当前用户拥有的权限
Collection requiredAuths : 当前要求的权限,即ifAllGranted ,ifNotGranted,ifAnyGranted 属性的值

满足ifAllGranted: 只需要grantedAuths.containsAll(requiredAuths);返回true即可
满足ifAnyGranted: 只需要grantedAuths.retainAll(requiredAuths);有内容即可(两集合有交集)
满足ifNotGranted:与Any相反,如果没有交集即可

点赞
收藏
评论区
推荐文章
刚刚好 刚刚好
4个月前
css问题
1、在IOS中图片不显示(给图片加了圆角或者img没有父级)<div<imgsrc""/</divdiv{width:20px;height:20px;borderradius:20px;overflow:h
晴空闲云 晴空闲云
4个月前
css中box-sizing解放盒子实际宽高计算
我们知道传统的盒子模型,如果增加内边距padding和边框border,那么会撑大整个盒子,造成盒子的宽度不好计算,在实务中特别不方便。boxsizing可以设置盒模型的方式,可以很好的设置固定宽高的盒模型。盒子宽高计算假如我们设置如下盒子:宽度和高度均为200px,那么这会这个盒子实际的宽高就都是200px。但是当我们设置这个盒子的边框和内间距的时候,那
艾木酱 艾木酱
3个月前
快速入门|使用MemFire Cloud构建React Native应用程序
MemFireCloud是一款提供云数据库,用户可以创建云数据库,并对数据库进行管理,还可以对数据库进行备份操作。它还提供后端即服务,用户可以在1分钟内新建一个应用,使用自动生成的API和SDK,访问云数据库、对象存储、用户认证与授权等功能,可专
Wesley13 Wesley13
1年前
CAS 4.1.x 单点登出(退出登录)的原理解析
  我们在项目中使用了cas作为单点登录的解决方案,当在集成shiro做统一权限控制的时候,发现单点退出登录有坑,所以啃了一下CAS的单点登出的源码,在此分享一下。1、回顾单点登录中一些关键事件  在解析CAS单点登出的原理之前,我们先回顾一下在单点登录过程中,CAS服务器和CAS客户端都做了一些什么事,这些事
Stella981 Stella981
1年前
Apache Sentry实战之旅(一)—— Impala+Sentry整合
Impala默认是以impala这个超级用户运行服务,执行DML和DDL操作的,要实现不同用户之间细粒度的权限控制,需要与Sentry整合。Sentry是Apache下的一个开源项目,它基于RBAC的授权模型实现了权限控制,Impala与它整合以后,就能实现不同用户之间在应用层的权限认证,从而控制用户的DML、DDL
Stella981 Stella981
1年前
Spring Security 实战干货:OAuth2第三方授权初体验
1\.前言现在很多项目都有第三方登录或者第三方授权的需求,而最成熟的方案就是OAuth2.0授权协议。SpringSecurity也整合了OAuth2.0,在目前最新的SpringSecurity5中整合了OAuth2.0的客户端,我们可以很方便的使用SpringSecurityOAuth2来实现相关的需求。接下来跟着胖哥
Stella981 Stella981
1年前
Spring Security OAuth2 SSO
通常公司肯定不止一个系统,每个系统都需要进行认证和权限控制,不可能每个每个系统都自己去写,这个时候需要把登录单独提出来1.登录和授权是统一的2.业务系统该怎么写还怎么写!(https://oscimg.oschina.net/oscnet/87496320180711181735072935217297.png)
Wesley13 Wesley13
1年前
RBAC模型
RBAC基于角色的访问控制(RoleBasedAccessControl)作为传统访问控制(自主访问,强制访问)的有前景的代替受到广泛的关注。在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。在一个组织中,角色是为了完成各种工作而创造,用户则依据它的责任和资格来被指派相应的角色,用
Stella981 Stella981
1年前
Spring Security修炼手册(四)————Security默认表达式的权限控制
       前三章主要讲的是Security对于认证的处理,那么本节,会为大家介绍基于Security默认表达式的权限控制(较为简单,无法满足复杂权限控制及多变的权限规则,后面会介绍基于自定义表达式的权限访问控制,可满足99%的业务场景的需求)。一、介绍及使用 直接进入主题,基于默认的表达式权限控制,需要在SecurityConf
helloworld_28799839 helloworld_28799839
4个月前
常用知识整理
Javascript判断对象是否为空jsObject.keys(myObject).length0经常使用的三元运算我们经常遇到处理表格列状态字段如status的时候可以用到vue