Spring Security入门(基于SSM环境配置)
一、前期准备
- 配置 - SSM环境
二、不使用数据库进行权限控制
配置好SSM环境以后,配置SpringSecurity环境
- 添加 - 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>
- 在服务器启动该的时候读取 - springSecurity配置文件- 实现方法,通过application域对象实现,和整合 - spring和- mybatis的方法相同- <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配置文件。
- 使用过滤器链拦截所有的资源,来实现对资源的权限控制 
 
- 书写 - 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中使用
 
- 配置成功和失败的处理器 - 通过实现 - 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对象**
具体实现
- 数据库设计(具体情况具体考虑) - 三个表: - 用户表。存放具体的用户 
- 角色表。存放对应的角色。(管理员,会员,普通用户) 
- 权限表。存放具体的权限。(增加,删除,修改,查询权限的控制) 
 
- 每一个用户可以有多个角色,一个角色也可以有多个权限 - 用户和角色。多对多的关系 
- 角色和权限。多对多的关系 
 
 
- 编写数据库表的 - ORM映射,编写持久层接口,服务层接口
- 创建实现 - 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提供了为密码加密的算法
步骤
- 为数据库中的密码加密 - 通过 - 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);
- 登陆时实现解密 - 创建 - BCryptPasswordEncoder类的- bean对象
- 在 - <security:authentication-proider>标签中引用
 
Spring Security入门(基于SSM环境配置)的更多相关文章
- SpringBoot集成Spring Security入门体验
		一.前言 Spring Security 和 Apache Shiro 都是安全框架,为Java应用程序提供身份认证和授权. 二者区别 Spring Security:重量级安全框架 Apache S ... 
- 030 SSM综合练习06--数据后台管理系统--SSM权限操作及Spring Security入门
		1.权限操作涉及的三张表 (1)用户表信息描述users sql语句: CREATE TABLE users ( id ) DEFAULT SYS_GUID () PRIMARY KEY, email ... 
- Spring Security 入门(基本使用)
		Spring Security 入门(基本使用) 这几天看了下b站关于 spring security 的学习视频,不得不说 spring security 有点复杂,脑袋有点懵懵的,在此整理下学习内 ... 
- Spring Security(08)——intercept-url配置
		http://elim.iteye.com/blog/2161056 Spring Security(08)--intercept-url配置 博客分类: spring Security Spring ... 
- Spring Security 入门详解(转)
		1.Spring Security介绍 Spring Security是基于spring的应用程序提供声明式安全保护的安全性框架,它提供了完整的安全性解决方案,能够在web请求级别和方法调用级别 处理 ... 
- Spring Security 入门详解
		序:本文主要参考 spring实战 对里面的知识做一个梳理 1.Spring Security介绍 Spring Security是基于spring的应用程序提供声明式安全保护的安全性框架,它提供了完 ... 
- Spring - IoC(8): 基于 Annotation 的配置
		除了基于 XML 的配置外,Spring 也支持基于 Annotation 的配置.Spring 提供以下介个 Annotation 来标注 Spring Bean: @Component:标注一个普 ... 
- PHP入门及服务环境配置(Nginx+PHP)
		PHP入门及服务环境配置(Nginx+PHP) PHP入门 PHP维基百科: PHP(全称:PHP:Hypertext Preprocessor,即"PHP:超文本预处理器")是一 ... 
- Spring Security 入门(1-2)Spring Security - 从 配置例子例子 开始我们的学习历程
		1.Spring Security 的配置文件 我们需要为 Spring Security 专门建立一个 Spring 的配置文件,该文件就专门用来作为 Spring Security 的配置. &l ... 
随机推荐
- 爬虫:Selenium + PhantomJS
			更:Selenium特征过多(language/UserAgent/navigator/en-US/plugins),以Selenium打开的浏览器处于自测模式,很容易被检测出来,解决方法可选: 用m ... 
- 04Redis入门指南笔记(内部编码规则简介)
			Redis是一个基于内存的数据库,所有的数据都存储在内存中.所以如何优化存储,减少内存空间占用是一个非常重要的话题.精简键名和键值是最直观的减少内存占用的方式,如将键名very.important.p ... 
- Istio on ACK集成生态(1): 集成TSDB助力可观测性存储
			阿里云容器服务Kubernetes(简称ACK)支持一键部署Istio,可以参考文档在ACK上部署使用Isito.Istio on ACK提供了丰富的监控能力,为网格中的服务收集遥测数据,其中Mixe ... 
- @loj - 6353@「CodePlus 2018 4 月赛」组合数问题 2
			目录 @description@ @solution@ @accepted code@ @details@ @description@ 请你找到 k 个不同的组合数,使得对于其中任何一个组合数 \(C ... 
- gensim的word2vec如何得出词向量(python)
			首先需要具备gensim包,然后需要一个语料库用来训练,这里用到的是skip-gram或CBOW方法,具体细节可以去查查相关资料,这两种方法大致上就是把意思相近的词映射到词空间中相近的位置. 语料库t ... 
- PyCharm indexing goes into infinite loop   pycharm 不同的indexing
			https://stackoverflow.com/questions/24955896/pycharm-indexing-goes-into-infinite-loop 5 1 I opened u ... 
- C#的选择语句练习(一)
			1.请输入一个数x,若x<1,则y=x:若1<=x<10,则y=2x-1:若x>=10,则y=3x-11,要求随意输入一个x值,求出y值. 2.输入问题[你有房子吗?],若回答 ... 
- H3C 单路径网络中环路产生过程(3)
- P1000 A+B Problem
			题目描述 给定两个整数\(a,b\),输出它们的和. 输入格式 输入两个整数,表示\(a,b(1 \le a,b \le 10^9)\). 输出格式 输出一个整数,表示答案. 样例输入 20 30 样 ... 
- H3C CIDR
