`

SpringSecurity初体验

阅读更多
        刚刚接触SpringSecurity,根据网上的教程自己试了一下,记录下来以供日后查看。

参考文档

这里主要的参考文档是Spring Security的自带的Reference。网络上有一个它的中文翻译,地址如下:
[url]http://www.family168.com/tutorial/springsecurity/html/springsecurity.html
[/url]

Spring Security基本配置
1. 在web.xml文件中加入Filter声明
<!-- Spring security Filter -->
<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>


注意,springSecurityFilterChain这个名称是由命名空间默认创建的用于处理web安全的一个内部的bean的id。所以你在你的Spring配置文件中,不应该再使用这个id作为你的bean。

2. 使用最小的<http>配置
<http auto-config='true'>  
    <intercept-url pattern="/**" access="ROLE_USER" />  
</http>


3. 配置UserDetailsService来指定用户和权限
<authentication-provider>  
    <user-service>  
      <user name="downpour" password="downpour" authorities="ROLE_USER, ROLE_ADMIN" />  
      <user name="robbin" password="robbin" authorities="ROLE_USER" />  
      <user name="QuakeWang" password="QuakeWang" authorities="ROLE_ADMIN" />  
    </user-service>  
</authentication-provider>


security的XML头为
<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-2.5.xsd
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">



如此一番折腾之后,启动服务器,输入地址,系统会自动转向到SS自已的登陆界面,需要当前用户输入用户名、密码进行登陆验证。

接下来通过一个实例来加深理解
创建用户表:
CREATE TABLE [dbo].[USERS](
	[ID] [numeric](18, 0) PRIMARY KEY IDENTITY(1,1) NOT NULL,
	[NAME] [varchar](255) NULL,
	[PASSWORD] [varchar](255) NULL,
	[DISABLED] [varchar](255) NULL)


创建权限表:
CREATE TABLE [dbo].[ROLE](
	[ID] [numeric](18, 0) PRIMARY KEY IDENTITY(1,1) NOT NULL,
	[NAME] [varchar](255) NULL,
	[DESCRIPTION] [varchar](255) NULL)


创建用户权限关系表:
CREATE TABLE [dbo].[USER_ROLE](
	[USER_ID] [numeric](18, 0) NOT NULL,
	[ROLE_ID] [numeric](18, 0) NOT NULL);
ALTER TABLE [dbo].[USER_ROLE]  WITH CHECK ADD FOREIGN KEY([ROLE_ID])
REFERENCES [dbo].[ROLE] ([ID]);
ALTER TABLE [dbo].[USER_ROLE]  WITH CHECK ADD FOREIGN KEY([USER_ID])
REFERENCES [dbo].[USERS] ([ID]);


建立表相对应的bean
其中Users表需要进行修改一下
/**
 * 
 */
package admin.model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Transient;

import org.apache.commons.lang.StringUtils;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Proxy;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.userdetails.UserDetails;

/**
 * @author Downpour
 *
 */
@Entity
@Proxy(lazy = false)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Users implements UserDetails {
	
	private static final long serialVersionUID = 8026813053768023527L;

    @Id
	@GeneratedValue
	private Integer id;
	
	private String name;
	
	private String password;
	
	private boolean disabled;
	
	@ManyToMany(targetEntity = Role.class, fetch = FetchType.EAGER)
    @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
	private Set<Role> roles;
	
	@Transient
	private Map<String, List<Resource>> roleResources;
	
	/**
	 * The default constructor
	 */
	public Users() {
		
	}

	/* (non-Javadoc)
	 * @see org.springframework.security.userdetails.UserDetails#getAuthorities()
	 */
	public GrantedAuthority[] getAuthorities() {
		List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>(roles.size());
    	for(Role role : roles) {
    		grantedAuthorities.add(new GrantedAuthorityImpl(role.getName()));
    	}
        return grantedAuthorities.toArray(new GrantedAuthority[roles.size()]);
	}
	
	/**
	 * Returns the authorites string
	 * 
	 * eg. 
	 *    downpour --- ROLE_ADMIN,ROLE_USER
	 *    robbin --- ROLE_ADMIN
	 * 
	 * @return
	 */
	public String getAuthoritiesString() {
	    List<String> authorities = new ArrayList<String>();
	    for(GrantedAuthority authority : this.getAuthorities()) {
	        authorities.add(authority.getAuthority());
	    }
	    return StringUtils.join(authorities, ",");
	}

	/* (non-Javadoc)
	 * @see org.springframework.security.userdetails.UserDetails#getPassword()
	 */
	public String getPassword() {
		return password;
	}

	/* (non-Javadoc)
	 * @see org.springframework.security.userdetails.UserDetails#getUsername()
	 */
	public String getUsername() {
		return name;
	}

	/* (non-Javadoc)
	 * @see org.springframework.security.userdetails.UserDetails#isAccountNonExpired()
	 */
	public boolean isAccountNonExpired() {
		return true;
	}

	/* (non-Javadoc)
	 * @see org.springframework.security.userdetails.UserDetails#isAccountNonLocked()
	 */
	public boolean isAccountNonLocked() {
		return true;
	}

	/* (non-Javadoc)
	 * @see org.springframework.security.userdetails.UserDetails#isCredentialsNonExpired()
	 */
	public boolean isCredentialsNonExpired() {
		return true;
	}

	/* (non-Javadoc)
	 * @see org.springframework.security.userdetails.UserDetails#isEnabled()
	 */
	public boolean isEnabled() {
		return !disabled;
	}

	/**
	 * @return the id
	 */
	public Integer getId() {
		return id;
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @return the disabled
	 */
	public boolean isDisabled() {
		return disabled;
	}

	/**
	 * @return the roles
	 */
	public Set<Role> getRoles() {
		return roles;
	}

	/**
	 * @return the roleResources
	 */
	public Map<String, List<Resource>> getRoleResources() {
		// init roleResources for the first time
		if(this.roleResources == null) {
			
			this.roleResources = new HashMap<String, List<Resource>>();
			
			for(Role role : this.roles) {
				String roleName = role.getName();
				Set<Resource> resources = role.getResources();
				for(Resource resource : resources) {
					String key = roleName + "_" + resource.getType();
					if(!this.roleResources.containsKey(key)) {
						this.roleResources.put(key, new ArrayList<Resource>());
					}
					this.roleResources.get(key).add(resource);					
				}
			}
			
		}
		return this.roleResources;
	}

	/**
	 * @param id the id to set
	 */
	public void setId(Integer id) {
		this.id = id;
	}

	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @param password the password to set
	 */
	public void setPassword(String password) {
		this.password = password;
	}

	/**
	 * @param disabled the disabled to set
	 */
	public void setDisabled(boolean disabled) {
		this.disabled = disabled;
	}

	/**
	 * @param roles the roles to set
	 */
	public void setRoles(Set<Role> roles) {
		this.roles = roles;
	}
	
}


就是继承了UserDetails接口,UserDetails接口就是SS用来进行用户验证用的接口,这个接口的方法都很好实现,只有getAuthorities需要处理一下,用来返回用户的所有权限。

有了用户信息的实体存在了,当然还需要操作这些信息的实体,SS提供了另外一个接口UserDetailsService,这个接口只有一个方法loadUserByUsername(String s),用于根据用户名获取用户信息,我们编写一个SecurityManager类实现之
/**
 * 
 */
package admin.impl;

import java.util.List;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import admin.interfaces.SecurityManager;
import admin.model.Users;

/**
 * @author 
 */
@Service("securityManager")
public class SecurityManagerImpl extends HibernateDaoSupport implements UserDetailsService, SecurityManager {
    
    /**
     * Init sessionFactory here because the annotation of Spring 2.5 can not support override inject
     *  
     * @param sessionFactory
     */
    @Autowired
    public void init(SessionFactory sessionFactory) {
        super.setSessionFactory(sessionFactory);
    }
    
    /* (non-Javadoc)
     * @see org.springframework.security.userdetails.UserDetailsService#loadUserByUsername(java.lang.String)
     */
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException, DataAccessException {
        List<Users> users = getHibernateTemplate().find("FROM Users user WHERE user.name = ? AND user.disabled = false", userName);
        if(users.isEmpty()) {
            throw new UsernameNotFoundException("User " + userName + " has no GrantedAuthority");
        }
        return users.get(0);
    }   
}


调整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-2.5.xsd
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">
	
	<http access-denied-page="/403.jsp">  
		<intercept-url pattern="/login.jsp*" filters="none"/>
    	<intercept-url pattern="/**" access="ROLE_USER" />
    	<form-login login-page="/login.jsp" default-target-url="/admin/hello.jsp" always-use-default-target="true" authentication-failure-url="/login.jsp?error=true"/>
	    <logout logout-success-url="/login.jsp"/>  
	</http> 
	
	<authentication-manager alias="authenticationManager"/>
	
	<authentication-provider user-service-ref="securityManager">
		<password-encoder hash="md5"/>
	</authentication-provider>
</beans:beans> 


看得出来就是把authentication-provider的策略从XML里直接写死,改成了使用数据库来进行管理,而中间的操作类就是自定义的实现了UserDetailsService接口的securityManager类。一切似乎明朗起来。
分享到:
评论

相关推荐

    SpringSecurity初体验之手动配置用户名密码

    此文章是记录博主在学习springsecurity时的笔记 第一步 创建一个SpringBoot工程,勾选上需要的依赖。 第二步 创建一个名为securityconfig的配置类,该类基础了父类WebSecurityConfigurerAdapter(提供用于创建...

    从入门到高级实战-深度探索SpringSecurity安全框架视频.zip

    02.Spring Security 初体验 03.基于内存定义 Spring Security 用户 04.Spring Security 自定义表单登录 05.Spring Security 登录表单配置细节 06.Spring Security 表单登录源码 07.Spring Security 中的 JSON 交互 ...

    spring-security初体验demo

    这个"spring-security初体验demo"很可能是为了帮助初学者理解如何在实际项目中集成和配置Spring Security。下面,我们将深入探讨Spring Security的核心概念、工作原理以及如何通过实践来设置一个简单的示例。 ...

    详解SpringBoot+SpringSecurity+jwt整合及初体验

    SpringBoot+SpringSecurity+jwt整合详解 SpringBoot是当前最流行的Java框架之一,它提供了便捷的方式来构建基于Web的应用程序。然而,在构建Web应用程序时,安全性是不可忽视的重要方面。因此,本文将详细介绍如何...

    springsecuritytotp:使用Google Authenticator登录Spring Security(基于时间的一次性密码算法,TOTP)

    在本文中,我们将深入探讨如何使用Google Authenticator与Spring Security集成,实现基于时间的一次性密码算法(TOTP)的双因素身份验证。这是一项重要的安全措施,它为应用程序提供了额外的安全层,防止未经授权的...

    《Spring-Boot入门初体验》-视频教程-示例项目源代码 -SBTest.zip数学建模

    《Spring Boot入门初体验》视频教程提供了一个非常适合初学者的入门平台,通过实际的示例项目源代码,帮助学习者快速上手并深入理解Spring Boot的工作原理及其相关技术栈。 教程中的示例项目源代码通常包含多个模块...

    Acegi(四):Acegi初体验及初解剖

    在初体验部分,博主可能会介绍如何设置Acegi以保护一个简单的Spring应用,包括配置Spring XML文件、定义安全拦截器(filter)以及创建用户凭证。 身份验证过程通常涉及用户登录,Acegi支持多种认证方式,如基于表单...

    univers-2.0:EE JavaEE,Vaadin框架,Spring,Spring Security,Spring Boot,Maven,JPA,JBoss-WildFly

    Spring Security是Spring框架的一个子项目,专注于安全控制,如身份验证、授权等,为Web应用提供了强大的安全保障。 Spring Boot是Spring框架的扩展,旨在简化Spring应用的初始设置和常规配置。它通过“起步依赖”...

    xfire 初体验

    《Xfire初体验:探索Java Web服务框架》 在IT领域,Web服务是软件系统间交互的重要手段,而Xfire则是早期流行的一款基于Java的Web服务框架。它为开发者提供了构建和消费Web服务的便捷工具,尤其在XML-RPC和SOAP协议...

    spring开发指南

    《Spring开发指南》是一本专为Java开发者设计的详尽教程,无论你是初涉Spring框架的新手,还是希望深入理解并提升Spring应用的老手,它都能提供宝贵的指导。Spring是Java领域中最流行的轻量级开源框架之一,以其模块...

    基于Spring Boot的个人博客系统设计与实现

    Spring Security可以用来实现用户认证和授权,确保博客系统的安全性。对于文章的分类与标签,可以使用树形结构或标签云来展示,提供灵活的文章组织方式。评论系统可以通过Ajax异步技术实现实时更新,提高用户体验。...

    SpringBoot电影院购票系统毕业设计

    在本设计中,通过Spring Initializr快速生成项目的基础代码,接着添加必要的依赖,如Spring Web、Spring Data JPA、Spring Security等,这些依赖为构建RESTful API、数据库操作和安全控制提供了极大的便利。...

    基于Spring Boot的留学服务管理平台的设计与开发.zip

    系统后端则充分利用了Spring Boot框架的优势,整合了Spring Data JPA进行数据持久化,利用Spring Security实现安全控制,以及利用Spring MVC处理用户的请求和响应。RESTful API的广泛应用,使得前后端分离开发成为...

    128元尚硅谷Java视频教程_Spring Boot视频教程(下)整合篇

    4、尚硅谷-SpringBoot高级-缓存-@Cacheable初体验 5、尚硅谷-SpringBoot高级-缓存-缓存工作原理&@Cacheable运行流程 6、尚硅谷-SpringBoot高级-缓存-@Cacheable其他属性 7、尚硅谷-SpringBoot高级-缓存-@CachePut 8...

    【报告类】springboot vue基于Java的秦皇岛旅游景点管理系统1.docx

    Spring Boot内置了许多开箱即用的模块,如Spring Data JPA用于数据库操作、Spring Security用于安全控制、Spring MVC用于处理HTTP请求等。这些模块极大地减少了开发者的工作量,提高了系统的开发效率和可维护性。...

    springboot项目大学生入学审核系统的设计与实现.zip

    前端技术选型可以是React或Vue.js等现代前端框架,它们都具备响应迅速、组件化开发等优势,与Spring Boot结合可以大幅提升应用的开发效率和用户体验。 数据库方面,系统使用的是MySQL作为数据存储的解决方案,通过...

    springboot036海滨体育馆管理系统的设计与实现.zip

    Spring Security提供了全面的安全服务,包括用户认证、访问控制、CSRF防护等。通过这些安全机制的实现,系统能够有效地防止未授权访问和数据泄露风险。 本系统还设计了日志记录和异常处理机制,用于追踪系统运行...

    初涉StrutsMenu

    StrutsMenu可以与权限框架结合,如Spring Security或Apache Shiro,实现根据用户角色动态调整菜单的功能。 5. **源码阅读与定制**:作为开源工具,StrutsMenu的源码提供了学习和扩展的可能性。开发者可以根据自身...

    springboot043基于springboot的“衣依”服装销售平台的设计与实现.zip

    平台的后端开发主要利用Spring Boot整合各种组件,如Spring Data JPA进行数据持久化操作,Spring Security实现安全控制,以及Spring MVC处理Web请求等。这些组件的使用大幅提高了开发效率,同时保证了系统的稳定性和...

    基于vue的MOBA类游戏攻略分享平台--论文.zip

    使用Spring Security可以为平台提供安全控制,包括用户认证和授权,保证数据安全和用户隐私。同时,为了确保平台的高可用性和良好的用户体验,还需要对系统进行性能优化,比如通过缓存来减少数据库的压力,使用异步...

Global site tag (gtag.js) - Google Analytics