这几天项目中用到了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. js获取几个月前,几周前时间。

    /**  *  DK 命名空间  防止全局变量污染  */ var DK = {} ; /**  * 获取前几个月,默认为一个月,当前时间  * @author duke  * @date 格式为yy ...

  2. Servlet配置文件

    <url-pattern>/servlet/demo</url-pattern> 1.以 / 开头, /代表工程路径:(必须要加 / ) 2.以 * 开头,必须加后缀名 /* ...

  3. VIM中文乱码(_vimrc配置文件备份)

    _vimrc在用户目录下: set fileencodings=ucs-bom,utf-,cp936,gb18030,big5,euc-jp,euc-kr,latin1 set encoding=ut ...

  4. Linux下Tomcat安装、配置

    /etc/profile./etc/profile.d和.bash_profile区别 /etc/profile和/etc/profile.d区别 .bash_profile 是存放用户的全局变量 / ...

  5. Big Data應用:以"玩家意見"之數據分析來探討何謂"健康型線上遊戲"(上)

    首先,所有資料都可以從網路上找到,只是我做了一些分析與整理而已.純粹分享心得~~ 最近再做研究的時候我跟我的同事K先生在某次偶然的討論中發現了一件有趣的事情. [疑~~~~~~~新楓之谷的玩家人氣指數 ...

  6. Java-Android 之页面的跳转和结构的搭建

    Android中每个页面就是一个Activity,要合理的让这些页面实现跳转,才是关键,这里讲一个最简单的 首先,有一个主页面main.xml <?xml version="1.0&q ...

  7. Fragment的生命周期和Activity之间的通信以及使用

    Fragment通俗来讲就是碎片,不能单独存在,意思就是说必须依附于Activity,一般来说有两种方式把Fragment加到Activity,分为静态,动态. 静态即为右键单击,建立一个Fragme ...

  8. c语言学习之基础知识点介绍(二):格式化控制符和变量的补充

    上节简单介绍了c语言中的一些基础知识点,本节将对之前介绍的不够详细的知识点进行补充. 格式化控制符的消息介绍: %d的其他控制符: 1.%md:m代表这个整数位占用多少位,m是一个整数.实际数字不足的 ...

  9. shiro认证

    一.通过ini文件初始化一个用户 1.通过ini配置文件创建securityManager2.调用subject.login方法主体提交认证,提交的token3.securityManager进行认证 ...

  10. iOS:iOS开发中用户密码保存位置

    原文来自简书:http://www.jianshu.com/p/4af3b8179136/comments/1294203 如果要实现自动登录,不必每次打开应用都去登录,我们势必要把密码保存到本地.一 ...