没事就来了解下spring security.网上找了很多资料。有过时的,也有不是很全面的。各种问题也算是让我碰了个遍。这样吧。我先把整个流程写下来,之后在各个易混点分析吧。

1.建立几个必要的页面。

login.jsp   index.jsp    user.jsp     admin.jsp    error.jsp 后面几个只是用来做跳转的,里面没什么要注意的,就贴出login里面的吧

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>login</title>
</head>
<body>
<form action="/mavenTest/j_spring_security_check" method="post">
账户:<input type="text" name="j_username" id="username"/>
密码:<input type="text" name="j_password" id="password"/>
<input type="submit" value="登陆"/>
</form>
</body>
</html>

2.配置web.xml  没有用的就没有粘贴了

<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>

3.忘记吧pom.xml文件给出来了  版本为<org.springframework-version>3.2.3.RELEASE</org.springframework-version>

<!-- spring security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${org.springframework-version}</version>
</dependency> <dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${org.springframework-version}</version>
</dependency> <dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${org.springframework-version}</version>
</dependency>

4.配置spring security .xml文件

<?xml version="1.0" encoding="UTF-8"?>
<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.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd"> <!-- 不需要进行安全认证的资源 -->
<http pattern="/resources/**" security="none" />
<http pattern="/login.jsp" security="none"/> <!-- 资源所需要的权限 -->
<http auto-config='true'>
<form-login login-page="/login.jsp"
default-target-url="/index.jsp"
authentication-failure-url="/login.jsp?error=true" />
<logout logout-success-url="/index.jsp"/> <!-- 尝试访问没有权限的页面时跳转的页面 -->
<access-denied-handler error-page="/error-noauth.jsp"/> <custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR"/>
</http> <!-- 自定义一个filter,必须包含authenticationManager,accessDecisionManager,
securityMetadataSource三个属性 所有的功能都在这三个类中实现--> <beans:bean id="myFilter" class="com.demo.im.model.security.MyFilterSecurotyInterceptor">
<beans:property name="authenticationManager"
ref="authenticationManager" />
<beans:property name="accessDecisionManager"
ref ="myAccessDecisionManagerBean"/>
<beans:property name="securityMetadataSource"
ref="securityMetadaSource"/>
</beans:bean> <!-- 认证管理器,实现用户认证的入口,主要实现userdetailsservice -->
<authentication-manager alias="authenticationManager">
<authentication-provider
user-service-ref="myUserDetailService">
</authentication-provider>
</authentication-manager> <beans:bean id="myUserDetailService"
class="com.demo.im.model.security.DefaultUserDetailsService">
</beans:bean> <!-- 访问决策,决定某个用户具有的角色,是否有足够的权限去访问某个资源 -->
<beans:bean id="myAccessDecisionManagerBean"
class="com.demo.im.model.security.MyAccessDecisionManager" /> <beans:bean id="securityMetadaSource"
class="com.demo.im.model.security.MyInvocationSecurityMetadaSource"/> </beans:beans>

5.MyFilterSecurotyInterceptor   自定义filter的代码如下。

其中最核心的代码是  invoke() 方法中的

InterceptorStatusToken token = super.beforeInvocation(fi);
这一句在dofilter之前进行权限验证,而具体的实现交给了accessDecisionManager,下面将继续讨论
package com.demo.im.model.security;

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.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 MyFilterSecurotyInterceptor extends AbstractSecurityInterceptor implements Filter { private FilterInvocationSecurityMetadataSource securityMetadataSource; @Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub } @Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException { FilterInvocation fi = new FilterInvocation(request, response,chain);
invoke(fi);
} @Override
public void destroy() {
// TODO Auto-generated method stub } @Override
public Class<?> getSecureObjectClass() {
// TODO Auto-generated method stub
return FilterInvocation.class;
} @Override
public SecurityMetadataSource obtainSecurityMetadataSource() {
// TODO Auto-generated method stub
return this.securityMetadataSource;
} public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
return securityMetadataSource;
} public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource) {
this.securityMetadataSource = securityMetadataSource;
} public void invoke(FilterInvocation fi) throws IOException
,ServletException{ InterceptorStatusToken token = super.beforeInvocation(fi);
try {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} catch (Exception e) {
// TODO: handle exception
}finally{
super.afterInvocation(token, null);
}
}
}

6.DefaultUserDetailsService的实现

在这个类中你可以通过读取数据库来进行权限赋值,下面的代码未注解的是我写的静态的

package com.demo.im.model.security;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service; import com.demo.im.entity.Role;
import com.demo.im.entity.TUser;
import com.demo.im.model.dao.TUserMapper;
@Service
public class DefaultUserDetailsService implements UserDetailsService {
@Autowired
TUserMapper userDao; @Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
// TODO Auto-generated method stub
System.out.println("userDetail********");
Collection <GrantedAuthority> auths = new ArrayList<GrantedAuthority>(); GrantedAuthority auth2 = new GrantedAuthorityImpl("ROLE_ADMIN"); auths.add(auth2); User user = new User(username,"1111",true,true,true,true,auths);
return user; // TUser paramU = new TUser();
// paramU.setUsername(username);
// List<TUser> userList = userDao.selectByUserParam(paramU);
// TUser user = new TUser();
// if(userList==null || userList.size()<=0){
// throw new UsernameNotFoundException("username");
// }
// //得到用户权限
// if(user.getRoles()!=null && user.getRoles().size()>0){
//
// for(Role role : user.getRoles()){
// GrantedAuthority grantedAuthority = new GrantedAuthorityImpl(
// role.getRolecode().toUpperCase());
// auths.add(grantedAuthority);
// }
//
// }
// user.setAuthorities(auths);
// return user;
} }

7.MyInvocationSecurityMetadaSource类的内容

这个类说白了就是从数据库中取出资源对应的权限,我这里也是写的静态的,修改为动态的方法也很简单,执行一个查询就行了

package com.demo.im.model.security;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map; import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; public class MyInvocationSecurityMetadaSource
implements FilterInvocationSecurityMetadataSource{ // private UrlMatcher urlMatcher = new AntUrlPathMatcher();
private static Map<String,Collection<ConfigAttribute>> resourceMap = null; public MyInvocationSecurityMetadaSource(){
loadResourceDefine();
} private void loadResourceDefine(){
resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>(); ConfigAttribute ca = new SecurityConfig("ROLE_ADMIN"); atts.add(ca);
resourceMap.put("/user.jsp", atts);
resourceMap.put("/admin.jsp", atts);
resourceMap.put("/index.jsp",atts); } @Override
public Collection<ConfigAttribute> getAttributes(Object object)
throws IllegalArgumentException {
// TODO Auto-generated method stub
String url = ((FilterInvocation)object).getRequestUrl();
Iterator<String> ite = resourceMap.keySet().iterator(); while(ite.hasNext()){
String resURL = ite.next(); if(url.equalsIgnoreCase(resURL)){
return resourceMap.get(resURL);
} } return null;
} @Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
// TODO Auto-generated method stub
return null;
} @Override
public boolean supports(Class<?> clazz) {
// TODO Auto-generated method stub
return true;
} }

8.最后就是决策类了MyAccessDecisionManager

这个类就更好理解了,我们知道了用户的角色,我们也知道资源的角色,对比一下,也就是decide()一致就返回,不行就抛异常

package com.demo.im.model.security;

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{ @Override
public void decide(Authentication authentication, Object object,
Collection<ConfigAttribute> configAttributes) throws AccessDeniedException,
InsufficientAuthenticationException {
if(configAttributes == null){
return ;
}
System.out.println(object.toString());
Iterator<ConfigAttribute> ite = configAttributes.iterator();
while(ite.hasNext()){
ConfigAttribute ca = ite.next();
String needRole = ((SecurityConfig)ca).getAttribute(); for(GrantedAuthority ga : authentication.getAuthorities()){
if(needRole.equals(ga.getAuthority())){
return ;
}
}
}
throw new AccessDeniedException("no right"); } @Override
public boolean supports(ConfigAttribute arg0) {
// TODO Auto-generated method stub
return true;
} @Override
public boolean supports(Class<?> arg0) {
// TODO Auto-generated method stub
return true;
} }

9总结:

到这里一个基本的spring  security算是搭建完了。过会在来说说我遇到的坑。方便以后大家找自己的坑。

spring security 3.2 配置详解(结合数据库)的更多相关文章

  1. Spring 入门 web.xml配置详解

    Spring 入门 web.xml配置详解 https://www.cnblogs.com/cczz_11/p/4363314.html https://blog.csdn.net/hellolove ...

  2. Spring学习 6- Spring MVC (Spring MVC原理及配置详解)

    百度的面试官问:Web容器,Servlet容器,SpringMVC容器的区别: 我还写了个文章,说明web容器与servlet容器的联系,参考:servlet单实例多线程模式 这个文章有web容器与s ...

  3. Spring Security之Remember me详解

    Remember me功能就是勾选"记住我"后,一次登录,后面在有效期内免登录. 先看具体配置: pom文件: <dependency> <groupId> ...

  4. spring boot application properties配置详解

    # =================================================================== # COMMON SPRING BOOT PROPERTIE ...

  5. 笔记:Spring Cloud Ribbon 客户端配置详解

    自动化配置 由于 Ribbon 中定义的每一个接口都有多种不同的策略实现,同时这些接口之间又有一定的依赖关系,Spring Cloud Ribbon 中的自动化配置能够很方便的自动化构建接口的具体实现 ...

  6. 电商网站开发记录(三) Spring的引入,以及配置详解

    1.web.xml配置注解<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi=& ...

  7. Spring Cloud Eureka 常用配置详解,建议收藏!

    前几天,栈长分享了 <Spring Cloud Eureka 注册中心集群搭建,Greenwich 最新版!>,今天来分享下 Spring Cloud Eureka 常用的一些参数配置及说 ...

  8. Spring声明式事务配置详解

    Spring支持编程式事务管理和声明式的事务管理. 编程式事务管理 将事务管理代码嵌到业务方法中来控制事务的提交和回滚 缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码 声明式事务管理 一般情 ...

  9. Spring MVC原理及配置详解

    Spring MVC概述: Spring MVC是Spring提供的一个强大而灵活的web框架.借助于注解,Spring MVC提供了几乎是POJO的开发模式,使得控制器的开发和测试更加简单.这些控制 ...

随机推荐

  1. 常见的JAVA包

    java.lang 提供利用 Java 编程语言进行程序设计的基础类.最重要的类是 Object(它是类层次结构的根)和 Class(它的实例表示正在运行的应用程序中的类). java.util 包含 ...

  2. 纯CSS实现下拉菜单及下拉容器等(纯CSS实现导航条及导航下拉容器)

    虽然网上类似甚至相同的案例有很多,但是我还是写下,以记下笔记,也可供大家参考 希望大家可以指导批评~~ 首先我们以列表ul li 来开始我们菜单也可以说导航条的制作: 在页面中我们首先构建以下XHTM ...

  3. chm转换为html

    在Windows下chm转换为html的超简单方法(反编译CHM文件的方法) 通过调用Windows命令,将chm 文件转换为html 文件. 方法: 命令行(cmd),输入hh -decompile ...

  4. MS SQL数据类型比较

    字符串数据类型 char此数据类型可存储1~8000个定长字符串,字符串长度在创建时指定:如未指定,默认为char(1).每个字符占用1byte存储空间.nchar此数据类型可存储1~4000个定长U ...

  5. 带阈值的平滑l0范数加速稀疏恢复——同名英文论文翻译

    原文链接:Thresholded Smoothed l0 Norm for Accelerated Sparse Recovery http://ieeexplore.ieee.org/documen ...

  6. 【搬运】systemctl 命令完全指南

    Systemctl是一个systemd工具,主要负责控制systemd系统和服务管理器. Systemd是一个系统管理守护进程.工具和库的集合,用于取代System V初始进程.Systemd的功能是 ...

  7. Web自动化测试工具调研

    背景 Web自动化测试越来越被重视, 因为现在Web已经是工程化的状态. 如何通过工具测试, 保证Web开发的质量,提升开发效率,是Web工具的诞生的来由. Web测试分为以下几个方面: 1. 界面测 ...

  8. jquery easyui-datagrid/treegrid 清空数据参考

    在使用easyui的treegrid或datagrid的过程经常会有这样的场景,如:需要按不同的类型加载数据时,如果选择的分类下没有数据应该把上次展示的数据清空,以免引用歧义.下面给出两种方法供初学者 ...

  9. DS-5建工程

    DS-5教程-使用ARM DS-5 和DSTREAM仿真器调试裸机程序 http://bbs.elecfans.com/jishu_453909_1_1.html i2c( 楼主 )2014-10-1 ...

  10. Leetcode: Word Squares && Summary: Another Important Implementation of Trie(Retrieve all the words with a given Prefix)

    Given a set of words (without duplicates), find all word squares you can build from them. A sequence ...