这几天项目中用到了SpringSecurity做登陆安全。所以在这写一下也许可以帮助一下其他人,自己也熟悉一下

SpringSecurity配置文件如下:

<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd"> <!-- 这个元素用来在你的应用程序中启用基于安全的注解
<global-method-security pre-post-annotations="enabled" access-decision-manager-ref="myAccessDecisionManager"/>
-->
<http pattern="/index.html" security="none" /> <http auto-config="true">
<logout logout-success-url="/app/login" />
<form-login login-page="/app/login" default-target-url="/app/admin"
authentication-failure-url="/app/loginfailed" /> <!-- "记住我"功能,采用持久化策略(将用户的登录信息存放在数据库表中) -->
<!-- <remember-me data-source-ref="dataSource" /> --> <!-- 增加一个自定义的filter,放在FILTER_SECURITY_INTERCEPTOR之前,
实现用户、角色、权限、资源的数据库管理-->
<custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR"/> </http> <!-- 实现了UserDetailsService的Bean -->
<authentication-manager alias="myAuthenticationManager">
<authentication-provider user-service-ref="myUserDetailService">
<password-encoder hash="plaintext">
</password-encoder>
<!-- <password-encoder ref="passwordEncoder">
<salt-source user-property="username" />
</password-encoder> -->
</authentication-provider>
</authentication-manager> <!--
一个自定义的filter,必须包含
authenticationManager,
accessDecisionManager,
securityMetadataSource 三个属性。
-->
<beans:bean id="myFilter"
class="com.yihaomen.common.intercept.MyFilterSecurityInterceptor">
<!-- 用户拥有的权限 -->
<beans:property name="authenticationManager" ref="myAuthenticationManager"></beans:property>
<!-- 用户是否拥有所请求资源的权限 -->
<beans:property name="accessDecisionManager" ref="myAccessDecisionManager"></beans:property>
<!-- 资源与权限对应关系 -->
<beans:property name="securityMetadataSource" ref="mySecurityMetadataSource"></beans:property>
</beans:bean> </beans:beans>

所有的实现逻辑便在这个FilterInterceptor之中,主要的实现的是这个Interceptor中的三个属性,而实现的这三个类:

Interceptor:

package com.yihaomen.common.intercept;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
import org.springframework.security.access.intercept.InterceptorStatusToken;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter { // 与spring-security.xml里的myFilter的属性securityMetadataSource对应,
// 其他的两个组件,已经在AbstractSecurityInterceptor定义
@Autowired
private FilterInvocationSecurityMetadataSource securityMetadataSource; public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException { FilterInvocation fi = new FilterInvocation(request, response, chain);
invoke(fi); } public Class<? extends Object> getSecureObjectClass() {
return FilterInvocation.class;
} public void invoke(FilterInvocation fi) throws IOException,
ServletException {
// object为FilterInvocation对象
// super.beforeInvocation(fi);源码
// 1.获取请求资源的权限
// 执行Collection<ConfigAttribute> attributes =
// SecurityMetadataSource.getAttributes(object);
// 2.是否拥有权限
// this.accessDecisionManager.decide(authenticated, object, attributes);
InterceptorStatusToken token = super.beforeInvocation(fi); try {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} finally {
super.afterInvocation(token, null);
} } @Override
public SecurityMetadataSource obtainSecurityMetadataSource() {
return this.securityMetadataSource;
} public void setSecurityMetadataSource(
FilterInvocationSecurityMetadataSource securityMetadataSource) {
this.securityMetadataSource = securityMetadataSource;
} public void destroy() { } public void init(FilterConfig filterconfig) throws ServletException { } }
package com.yihaomen.comm.service;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import com.yihaomen.common.dao.ResourcesDao;
import com.yihaomen.common.domain.SysResource; public class MyInvocationSecurityMetadataSourceService implements
FilterInvocationSecurityMetadataSource { @Autowired
private ResourcesDao resourcesDao; // resourceMap及为key-url,value-Collection<ConfigAttribute>,资源权限对应Map
private static Map<String, Collection<ConfigAttribute>> resourceMap = null; public MyInvocationSecurityMetadataSourceService(ResourcesDao resourcesDao) {
this.resourcesDao = resourcesDao;
System.out.println("加载MyInvocationSecurityMetadataSourceService..."
+ resourcesDao);
loadResourceDefine();
} // 加载所有资源与权限的关系
private void loadResourceDefine() {
if (resourceMap == null) {
resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
List<SysResource> resources = resourcesDao.findAll();
// 加载资源对应的权限
for (SysResource resource : resources) {
Collection<ConfigAttribute> auths = resourcesDao
.loadRoleByResource(resource.getResource());
System.out.println("权限=" + auths);
resourceMap.put(resource.getResource(), auths);
}
}
} //由资源路径获得权限
//object为请求的资源路径
public Collection<ConfigAttribute> getAttributes(Object object)
throws IllegalArgumentException {
// object是一个URL,被用户请求的url
String requestUrl = ((FilterInvocation) object).getRequestUrl();
System.out.println("requestUrl is " + requestUrl); int firstQuestionMarkIndex = requestUrl.indexOf("?");
//如果请求的资源路径有?后面的参数,则将?后面的切掉,以免拒绝访问
if (firstQuestionMarkIndex != -1) {
requestUrl = requestUrl.substring(0, firstQuestionMarkIndex);
} if (resourceMap == null) {
loadResourceDefine();
}
//
Iterator<String> ite = resourceMap.keySet().iterator();
//根据资源路径获得其所需的权限
while (ite.hasNext()) {
String resURL = ite.next(); if (resURL.equals(requestUrl)) {
return resourceMap.get(resURL);
}
}
return null;
} public boolean supports(Class<?> arg0) {
// TODO Auto-generated method stub
return true;
} public Collection<ConfigAttribute> getAllConfigAttributes() {
// TODO Auto-generated method stub
return null;
} }
package com.yihaomen.comm.service;

import java.sql.SQLException;
import java.util.Collection; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException; import com.yihaomen.common.dao.UserInfoDao;
import com.yihaomen.common.domain.SysUser;
/**
* 根据用户名获得其所拥有的权限,返回该用户的状态信息。并将其所拥有的权限放入GrantedAuthority中
* @author Administrator
*
*/
public class MyUserDetailService implements UserDetailsService {
@Autowired
private UserInfoDao userInfoDao; @Autowired
private UserCache userCache; public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
System.out.println("username is :" + username); SysUser user = null;
try {
user = this.userInfoDao.findByName(username);
System.out.println(user);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // 获得用户权限
Collection<GrantedAuthority> auths = userInfoDao
.loadUserAuthorityByName(username); boolean enables = true;
// 账户过期否
boolean accountNonExpired = true;
// 证书过期否
boolean credentialsNonExpired = true;
// 账户锁定否
boolean accountNonLocked = true;
// 封装成spring security的user
User userdetail = new User(username, user.getPassword(), enables,
accountNonExpired, credentialsNonExpired, accountNonLocked,
auths);
for (GrantedAuthority s : auths) {
s.getAuthority();
}
System.out.println(auths);
return userdetail; } public UserInfoDao getUserInfoDao() {
return userInfoDao;
} public void setUserInfoDao(UserInfoDao userInfoDao) {
this.userInfoDao = userInfoDao;
} //设置用户缓存功能。
public UserCache getUserCache() {
return userCache;
} public void setUserCache(UserCache userCache) {
this.userCache = userCache;
} }
package com.yihaomen.comm.service;

import java.util.Collection;
import java.util.Iterator; import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority; public class MyAccessDecisionManager implements AccessDecisionManager { public void decide(Authentication authentication, Object object,
Collection<ConfigAttribute> configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException { if (configAttributes == null) {
return;
} //所请求的资源拥有的权限(一个资源对多个权限)
Iterator<ConfigAttribute> ite = configAttributes.iterator(); while (ite.hasNext()) { ConfigAttribute ca = ite.next();
//访问所请求资源所需要的权限
String needRole = ((SecurityConfig) ca).getAttribute();
System.out.println("needRole is " + needRole);
// ga 为用户所被赋予的权限。 needRole 为访问相应的资源应该具有的权限。
for (GrantedAuthority ga : authentication.getAuthorities()) { if (needRole.trim().equals(ga.getAuthority().trim())) { return;
} } }
//没有权限
throw new AccessDeniedException("没有权限访问!"); } public boolean supports(ConfigAttribute arg0) {
// TODO Auto-generated method stub
return true;
} public boolean supports(Class<?> arg0) {
// TODO Auto-generated method stub
return true;
} }

SpringSecurity数据库中存储用户、角色、资源的更多相关文章

  1. Spring-Security (学习记录三)--读取数据库中的用户和角色

    目录 1.先将hibernate的环境整合进来 2.创建一个数据库security,执行security.sql 3.修改spring-security.xml,采用数据库的方式读取用户跟角色 4.u ...

  2. SpringSecurity 自定义用户 角色 资源权限控制

    SpringSecurity 自定义用户 角色 资源权限控制 package com.joyen.learning.security; import java.sql.ResultSet; impor ...

  3. 数据库中存储日期的字段类型究竟应该用varchar还是datetime ?

    背景: 前段时间在百度经验看到一篇文章<如何在电脑右下角显示你(爱人)的名字>,之前也听过这个小技巧,但没真正动手设置过.所以出于好奇就实践了一下. 设置完成后的效果例如以下.右下角的时间 ...

  4. 批量替换数据库中所有用户数据表中字段数据类型为char和varchar到nvarchar的脚本

    解决问题:字段类型为char的总是占用指定字节长度(末尾好多空白符号),varchar数据类型长度一个汉字占2个字节,内容存储为中文的字段个人建议全部使用nvarchar. 操作说明:打开SQL Se ...

  5. SQL批量更新数据库中所有用户数据表中字段类型为tinyint为int

    --SQL批量更新数据库中所有用户数据表中字段类型为tinyint为int --关键说明:--1.从系统表syscolumns中的查询所有xtype='48'的记录得到类型为[tinyint]的字段- ...

  6. 查看MYSQL数据库中所有用户及拥有权限

    查看MYSQL数据库中所有用户 mysql> SELECT DISTINCT CONCAT('User: ''',user,'''@''',host,''';') AS query FROM m ...

  7. C# 在SQLite数据库中存储图像 z

    C# 在SQLite数据库中存储图像 更多 0 C# SQLite   建表语句 CREATE TABLE [ImageStore]([ImageStore_Id] INTEGER NOT NULL ...

  8. Oracle 18c 数据库中scott用户不存在的解决方法

    Oracle 18c 数据库中scott用户不存在的解决方法 注:该文为转载 上面标题可直接跳转 原文地址:http://www.cnblogs.com/zangdalei/p/5482732.htm ...

  9. 数据库中存储日期的字段类型到底应该用varchar还是datetime

    将数据库中存储时间的数据类型改为varchar(),这时最好让这些时间是数据库中自动生成的(一个没有格式的输入也可能会导致输出错误),因为存储类型为varchar(),所以获取到的值也就被认为是一个字 ...

随机推荐

  1. 使用泛型简单封装NGUI的ScrollView实现滑动列表

    懒,是老毛病了,周末跑了半马,跑完也是一通累,好久没锻炼了..也是懒的,有时都懒的写博客..最近看到项目中各种滑动列表框,本着要懒出水平来的原则,决定花点时间简单处理下(暂时未做列表太多时的优化):1 ...

  2. LeetCode——Remove Element

    Given an array and a value, remove all instances of that value in place and return the new length. T ...

  3. Linux进程间通信——使用数据报套接字

    前一篇文章, Linux进程间通信——使用流套接字介绍了一些有关socket(套接字)的一些基本内容,并讲解了流套接字的使用,这篇文章将会给大家讲讲,数据报套接字的使用. 一.简单回顾——什么是数据报 ...

  4. [Redux] Using withRouter() to Inject the Params into Connected Components

    We will learn how to use withRouter() to inject params provided by React Router into connected compo ...

  5. BP神经网络基本原理

    2.1 BP神经网络基本原理 BP网络模型处理信息的基本原理是:输入信号Xi通过中间节点(隐层点)作用于输出节点,经过非线形变换,产生输出信号Yk,网络训练的每一个样本包含输入向量X和期望输出量t,网 ...

  6. mybatis10 实现类代理对象开发

    mapper实现类代理对象开发 要想让mybatis自动创建dao接口实现类的代理对象,必须遵循一些规则: SqlSession sqlSession = sqlSessionFactory.open ...

  7. 字符集详解 ------------------------ UNICODE +UTF8

    http://my.oschina.net/goldenshaw/blog?catalog=3294521 http://my.oschina.net/goldenshaw/blog?catalog= ...

  8. python学习笔记--easy_install和pip

    "A tool for installing and managing Python packages"     --pip easy_insall和pip都提供了在线一键安装模块 ...

  9. 使用JAXB来实现Java合xml之间的转换

    使用jaxb操作Java与xml之间的转换非常简单,看个例子就明白了. //javaBean-->xml @Test public void test1() { try { JAXBContex ...

  10. dhcp源码编译支持4G上网卡

    1. tar xvzf dhcp-4.2.5-P1.tar.gz 2. ./configure --host=arm-linux ac_cv_file__dev_random=yes 3. vi bi ...