一、前期准备

  • 配置SSM环境

二、不使用数据库进行权限控制

配置好SSM环境以后,配置SpringSecurity环境

  1. 添加security依赖

     
     <dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>4.1.0.RELEASE</version>
    </dependency>
    <dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>4.1.0.RELEASE</version>
    </dependency>
  2. 在服务器启动该的时候读取springSecurity配置文件

    实现方法,通过application域对象实现,和整合springmybatis的方法相同

     <listener>
    <listener-class>
    org.springframework.web.context.ContextLoaderListener
    </listener-class>
    </listener>
    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
    classpath:springSecurity.xml
    </param-value>
    </context-param>
    <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>
    • 通过spring提供的监听器加载security配置文件。

    • 使用过滤器链拦截所有的资源,来实现对资源的权限控制

  3. 书写springSecurity配置文件

 <security:http>
<security:intercept-url pattern="add" access="hasAuthority('ROLE_USER')" />
<security:intercept-url pattern="index.jsp" access="permitAll()"/>
<security:intercept-url pattern="/login" access="permitAll()"/>
<security:intercept-url pattern="/*" access="isFullyAuthenticated()"/>
<security:form-login login-page="/login" login-processing-url="/login"
authentication-failure-handler-ref="failureHandler"
authentication-success-handler-ref="successHandler">
</security:form-login>
<security:csrf disabled="true"></security:csrf>
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user
name="username"
password="username"
authorities="ROLE_USER">
</security:user>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>

<bean id="successHandler" class="com.bywlstudio.security.SuccessHandler"></bean>
<bean id="failureHandler" class="com.bywlstudio.security.FailureHandler"></bean>
  • security:http配置权限拦截的方式是基于HTTP

  • 资源拦截方式,有两种

    • security:form-login基于表单(常用)

      • security默认提供一个登陆界面,可以自定义

      • login-page指定登陆界面(注:用户名的name属性必须为username,密码的name属性必须为password。这是security判断用户输入是否正确的标准)

      • login-processing-url指定登陆界面的表单的提交路径

      • authentication-failure-handler-ref引用一个密码错误以后的处理方式(上面的使用了bean引用)

      • authentication-success-handler-ref应用一个成功以后的处理方式

    • security:http-basic基本的验证方式(不常用)

  • secutity:authentication-manager具体的权限管理配置

  • security:intercept-url配置需要拦截的资源

    • access配置可以访问的权限(取值参考:security官方文档

    • pattern配置需要拦截的资源(上面的资源使用MVC控制)

  • security:csrf一种浏览器的防护机制,后期文章会详细说明

  • security:authentication-provider具体的实现权限控制

  • security:user配置一个具体的用户

    • authorities配置当前用户所具有的权限,在intercept-url中使用

  1. 配置成功和失败的处理器

    通过实现AuthenticationSuccessHandler接口和AuthenticationFailureHandler实现

     
    public class FailureHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e)
    throws IOException, ServletException {
    response.getWriter().write(WriteStatusJson.loginStatus("status","Failure"));
    }
    }

    public class SuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
    response.getWriter().write(WriteStatusJson.loginStatus("status","success"));
    }
    }
     ​
    • WriteStatusJson这个类是笔者自定义的一个回状态的工具类,具体实现如下

       
      public class WriteStatusJson {
      /**
      * 返回登陆状态信息
      * @param attritute 登陆的状态
      * @param value 登陆的成功过或者失败的返回值
      * @param <E> 根据每一次状态返回的值而定
      * @return {String} 返回一个json字符串
      * @throws JsonProcessingException
      */
      public static <E> String loginStatus(String attritute , E value)
      throws JsonProcessingException {
      ObjectMapper objectMapper = new ObjectMapper();
      Map<String,E> map = new HashMap<>();
      map.put(attritute,value);
      return objectMapper.writeValueAsString(map);
      }
      }
      • 主要功能,将需要返回的状态信息转换为字符串(字符串转换使用了Jackson

此时一个基本的权限功能已经结束。


三、通过数据库实现权限控制

存在的问题

  • 用户已经写死,需要增加用户只能通过修改xml文件。

解决问题的思路

  • 通过Java代码生成一个User并且赋予它一定的权限

  • 引用入一个接口UserDetailsSevrice重写里面的方法loadUserByUsername

  • 方法返回值是一个UserDetails类型,Spring提供了一个类User实现了UserDetails查看User类的源码

 
private static final long serialVersionUID = 410L;//序列化
private String password;//密码
private final String username;//用户名
private final Set<GrantedAuthority> authorities;//权限的集合
private final boolean accountNonExpired;//权限是否过期
private final boolean accountNonLocked;//权限是否被锁定
private final boolean credentialsNonExpired;//凭据未过期
private final boolean enabled;//账户可以使用
  • 创建管理用户权限的类

 
public class UserAuthent implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
User user = new User("MakerStack","love", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER,ROLE_ADMIN"));
return user;
}
}
  • AuthorityUtils工具类给用户赋予权限,类似于xml中的authorities属性


存在的问题

  • 用户还是写死的,只能用过spring自带的User对象来赋值,不能连接数据库

解决思路

  • 上面提到spring自带的User通过实现了UserDetails接口来实现对用户权限的添加

  • 自定义User类实现UserDetails接口,创建操纵User类的持久层接口,获取数据库中的User对象**

具体实现

  1. 数据库设计(具体情况具体考虑)

    • 三个表:

      • 用户表。存放具体的用户

      • 角色表。存放对应的角色。(管理员,会员,普通用户)

      • 权限表。存放具体的权限。(增加,删除,修改,查询权限的控制)

    • 每一个用户可以有多个角色,一个角色也可以有多个权限

      • 用户和角色。多对多的关系

      • 角色和权限。多对多的关系

  2. 编写数据库表的ORM映射,编写持久层接口,服务层接口

  3. 创建实现UserDetailsService接口的类,实现方法

     User user = userService.findUserByUsername(username);
    if(user!=null){
    List<Authority> authorities = userService.findAuthorityByUsername(username);
    //需要对user的List<Authority>集合赋值
    List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
    for (Authority authority : authorities) {
    GrantedAuthority grantedAuthority =
    new SimpleGrantedAuthority(authority.getTag());
    grantedAuthorities.add(grantedAuthority);
    }
    user.setAuthorities(grantedAuthorities);
    }
    return user;
    • 方法loadUserByUsername方法的参数即为用户在表单中输入的用户名(后期会出一篇security执行流程的文章,可以关注一下)

    • 通过用户名获取对应的用户信息,判断用户是否存在,存在即获取其对应的权限信息;若不存在则直接返回

    • 实体类User实现了UserDetails接口,内部定义了一个存储用户权限的集合。现在需要做的就是将数据库中的权限信息添加到这个集合中。

    • 通过spring提供的接口GrantedAuthority来实现;通过其子类SimpleGrantedAuthority将数据库中的权限信息写入,赋值给GrantedAuthority类型,添加到一个集合中,将这个集合赋值给user类的权限集合

      数据库整合完成

需要注意的问题

  • 登陆界面的name属性必须保证,否则会出现loadUserByUsername方法获取不到参数的问题

    • 用户名为username

    • 密码为password

    • 否则security无法读取

  • 若有读者出现这个错误

    • Access denied for user 'root'@'localhost'(using password: YES)且你之前连接数据库是正确的,则检查你得数据库配置文件


四、密码加密

目前数据库中存放的密码均为明文传输,所以需要对密码进行加密,而security提供了为密码加密的算法

步骤

  1. 为数据库中的密码加密

    • 通过security提供的接口PasswordEncoder的实现类BCryptPasswordEncoder实现用户密码的加密和匹配

    • 接口PasswordEncoder中的方法

     
    String encode(CharSequence var1);

    boolean matches(CharSequence var1, String var2);
    • 实现加密

     
    PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    //哈希算法+变量
    String encode = passwordEncoder.encode("123456");
    User user = new User();
    user.setId(3);
    user.setPassword(encode);
    userService.updateUserPassword(user);
  2. 登陆时实现解密

    • 创建BCryptPasswordEncoder类的bean对象

    • <security:authentication-proider>标签中引用


Spring Security入门(基于SSM环境配置)的更多相关文章

  1. SpringBoot集成Spring Security入门体验

    一.前言 Spring Security 和 Apache Shiro 都是安全框架,为Java应用程序提供身份认证和授权. 二者区别 Spring Security:重量级安全框架 Apache S ...

  2. 030 SSM综合练习06--数据后台管理系统--SSM权限操作及Spring Security入门

    1.权限操作涉及的三张表 (1)用户表信息描述users sql语句: CREATE TABLE users ( id ) DEFAULT SYS_GUID () PRIMARY KEY, email ...

  3. Spring Security 入门(基本使用)

    Spring Security 入门(基本使用) 这几天看了下b站关于 spring security 的学习视频,不得不说 spring security 有点复杂,脑袋有点懵懵的,在此整理下学习内 ...

  4. Spring Security(08)——intercept-url配置

    http://elim.iteye.com/blog/2161056 Spring Security(08)--intercept-url配置 博客分类: spring Security Spring ...

  5. Spring Security 入门详解(转)

    1.Spring Security介绍 Spring Security是基于spring的应用程序提供声明式安全保护的安全性框架,它提供了完整的安全性解决方案,能够在web请求级别和方法调用级别 处理 ...

  6. Spring Security 入门详解

    序:本文主要参考 spring实战 对里面的知识做一个梳理 1.Spring Security介绍 Spring Security是基于spring的应用程序提供声明式安全保护的安全性框架,它提供了完 ...

  7. Spring - IoC(8): 基于 Annotation 的配置

    除了基于 XML 的配置外,Spring 也支持基于 Annotation 的配置.Spring 提供以下介个 Annotation 来标注 Spring Bean: @Component:标注一个普 ...

  8. PHP入门及服务环境配置(Nginx+PHP)

    PHP入门及服务环境配置(Nginx+PHP) PHP入门 PHP维基百科: PHP(全称:PHP:Hypertext Preprocessor,即"PHP:超文本预处理器")是一 ...

  9. Spring Security 入门(1-2)Spring Security - 从 配置例子例子 开始我们的学习历程

    1.Spring Security 的配置文件 我们需要为 Spring Security 专门建立一个 Spring 的配置文件,该文件就专门用来作为 Spring Security 的配置. &l ...

随机推荐

  1. 19-1 djanjo中admin的简单用法

    1. 创建管理员账号 python3 manage.py createsuperuser 2. 在admin注册我们的表 在app目录下面的admin.py里面按以下语法注册 admin.site.r ...

  2. Linux系统服务及软件包的管理

     要点回顾 free命令查看内存 整理buffer与cache的作用 1.buffer(缓冲) 是为了提高内存和硬盘(或其他I/O设备)之间的数据交换的速度而设计的. 2.cache(缓存) 从CPU ...

  3. 2018-8-10-WPF-使用-VisualStudio-2017-项目文件

    title author date CreateTime categories WPF 使用 VisualStudio 2017 项目文件 lindexi 2018-08-10 19:16:53 +0 ...

  4. H3C IP的主要作用

  5. ITA 15.5 Optimal binary search trees

    p400 页最后一段 When j >= i , we need to select a root kr from among ki ... kj and then make an optima ...

  6. 用winrar和zip命令拷贝目录结构

    linux系统下使用zip命令 zip -r source.zip source -x *.php -x *.html # 压缩source目录,排除里面的php和html文件 windows系统下使 ...

  7. 机器学习-RBF高斯核函数处理

     机器学习-RBF高斯核函数处理 SVM高斯核函数-RBF优化 重要了解数学的部分: 协方差矩阵,高斯核函数公式. 个人建议具体的求法还是看下面的核心代码吧,更好理解,反正就我个人而言,烦躁的公式,还 ...

  8. Java中方法的格式

    [修饰符] 返回值类型 方法名([参数类型 形式参数1,参数类型 形式参数2,……]) {             执行语句;     [return 返回值;]//需要的话 } 参数列表(参数的类型 ...

  9. java 多线程之synchronized wait/notify解决买票问题

    一.Java线程具有五中基本状态 新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread(); 就绪状态(Runnable):当调用线程对象的st ...

  10. ERROR 1366 (HY000): Incorrect string value: '\xD5\xC5\xC8\xFD' for column 'name' at row 1

    ERROR 1366 (HY000): Incorrect string value: '\xD5\xC5\xC8\xFD' for column 'name'  at row 1   数据库字符集问 ...