`

扩展springsecurity的User类

阅读更多
扩展User类 实现更丰富的User属性
为了安装UserInfo没有提供属性set方法,赋值都在构造器中完成

首先实现UserDetails接口
package com.snda.swp.account.po;

import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import org.springframework.security.core.CredentialsContainer;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert;

//不可变类
public class UserInfo implements UserDetails, CredentialsContainer {

 private static final long serialVersionUID = 5997839307263494359L;

 // ~ Instance fields
 // ================================================================================================
 private String password;

 private String name;// 用户的中文姓名

 private String email;// 用户的邮箱地址

 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;

 // ~ Constructors
 // ===================================================================================================
 public UserInfo(String password, String name, String email,
   final String username,
   final Collection<? extends GrantedAuthority> authorities,
   final boolean accountNonExpired, final boolean accountNonLocked,
   final boolean credentialsNonExpired, final boolean enabled) {
  if (username == null || "".equals(username) || password == null)
   throw new IllegalArgumentException(
     "Cannot pass null or empty values to constructor");
  this.password = password;
  this.name = name;
  this.email = email;
  this.username = username;
  this.accountNonExpired = accountNonExpired;
  this.accountNonLocked = accountNonLocked;
  this.credentialsNonExpired = credentialsNonExpired;
  this.enabled = enabled;
  this.authorities = Collections
    .unmodifiableSet(sortAuthorities(authorities));
 }

 // ~ Methods
 // ========================================================================================================
 public Collection<GrantedAuthority> getAuthorities() {
  return authorities;
 }

 public String getPassword() {
  return password;
 }

 public String getUsername() {
  return username;
 }

 public String getEmail() {
  return email;
 }

 public String getName() {
  return name;
 }

 public boolean isAccountNonExpired() {
  return accountNonExpired;
 }

 public boolean isAccountNonLocked() {
  return accountNonLocked;
 }

 public boolean isCredentialsNonExpired() {
  return credentialsNonExpired;
 }

 public boolean isEnabled() {
  return enabled;
 }

 public void eraseCredentials() {
  password = null;
 }

 private static SortedSet<GrantedAuthority> sortAuthorities(
   Collection<? extends GrantedAuthority> authorities) {
  Assert.notNull(authorities,
    "Cannot pass a null GrantedAuthority collection");
  // Ensure array iteration order is predictable (as per
  // UserDetails.getAuthorities() contract and SEC-717)
  SortedSet<GrantedAuthority> sortedAuthorities = new TreeSet<GrantedAuthority>(
    new AuthorityComparator());

  for (GrantedAuthority grantedAuthority : authorities) {
   Assert.notNull(grantedAuthority,
     "GrantedAuthority list cannot contain any null elements");
   sortedAuthorities.add(grantedAuthority);
  }

  return sortedAuthorities;
 }

 private static class AuthorityComparator implements
   Comparator<GrantedAuthority>, Serializable {
  public int compare(GrantedAuthority g1, GrantedAuthority g2) {
   // Neither should ever be null as each entry is checked before
   // adding it to the set.
   // If the authority is null, it is a custom authority and should
   // precede others.
   if (g2.getAuthority() == null) {
    return -1;
   }

   if (g1.getAuthority() == null) {
    return 1;
   }

   return g1.getAuthority().compareTo(g2.getAuthority());
  }
 }

 @Override
 public boolean equals(Object rhs) {
  if (rhs instanceof UserInfo)
   return username.equals(((UserInfo) rhs).username);
  return false;
 }

 @Override
 public int hashCode() {
  return username.hashCode();
 }

 @Override
 public String toString() {
  StringBuilder sb = new StringBuilder();
  sb.append(super.toString()).append(": ");
  sb.append("Username: ").append(this.username).append("; ");
  sb.append("Password: [PROTECTED]; ");
  sb.append("Enabled: ").append(this.enabled).append("; ");
  sb.append("AccountNonExpired: ").append(this.accountNonExpired).append(
    "; ");
  sb.append("credentialsNonExpired: ").append(this.credentialsNonExpired)
    .append("; ");
  sb.append("AccountNonLocked: ").append(this.accountNonLocked).append(
    "; ");

  if (!authorities.isEmpty()) {
   sb.append("Granted Authorities: ");

   boolean first = true;
   for (GrantedAuthority auth : authorities) {
    if (!first) {
     sb.append(",");
    }
    first = false;

    sb.append(auth);
   }
  } else {
   sb.append("Not granted any authorities");
  }
  return sb.toString();
 }
}


实现UserDetailsService接口
package com.snda.swp.account.service;

import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.transaction.annotation.Transactional;
import com.google.common.collect.Sets;
import com.snda.swp.account.po.Authority;
import com.snda.swp.account.po.Role;
import com.snda.swp.account.po.User;
import com.snda.swp.account.po.UserInfo;

/**
 * 实现SpringSecurity的UserDetailsService接口,实现获取用户Detail信息的回调函数.
 *
 * @author calvin
 */
@Transactional(readOnly = true)
public class UserDetailsServiceImpl implements UserDetailsService {

 private AccountManager accountManager;

 /**
  * 获取用户Details信息的回调函数.
  */
 public UserDetails loadUserByUsername(String username)
   throws UsernameNotFoundException, DataAccessException {
  User user = accountManager.findUserByLoginName(username);
  if (user == null) {
   throw new UsernameNotFoundException("用户" + username + " 不存在");
  }

  Set<GrantedAuthority> grantedAuths = obtainGrantedAuthorities(user);

  // -- mini-web示例中无以下属性, 暂时全部设为true. --//
  boolean enabled = true;
  boolean accountNonExpired = true;
  boolean credentialsNonExpired = true;
  boolean accountNonLocked = true;

  UserInfo userdetails = new UserInfo(user.getPassword(), user.getName(),
    user.getEmail(), user.getLoginName(), grantedAuths,
    accountNonExpired, accountNonLocked, credentialsNonExpired,
    enabled);

  return userdetails;
 }

 /**
  * 获得用户所有角色的权限集合.
  */
 private Set<GrantedAuthority> obtainGrantedAuthorities(User user) {
  Set<GrantedAuthority> authSet = Sets.newHashSet();
  for (Role role : user.getRoleList()) {
   for (Authority authority : role.getAuthorityList()) {
    authSet.add(new GrantedAuthorityImpl(authority
      .getPrefixedName()));
   }
  }
  return authSet;
 }

 @Autowired
 public void setAccountManager(AccountManager accountManager) {
  this.accountManager = accountManager;
 }
}


重写SpringSecurityUtils类
package com.snda.swp.account.service;

import java.util.Collection;

import javax.servlet.http.HttpServletRequest;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;

import com.snda.swp.account.po.UserInfo;

/**
 * SpringSecurity的工具类.
 *
 * 注意. 本类只支持SpringSecurity 3.0.x.
 *
 * @author calvin
 */
public class SpringSecurityUtils {
 /**
  * 取得当前用户, 返回值为UserInfo类或其子类, 如果当前用户未登录则返回null.
  */
 @SuppressWarnings("unchecked")
 public static <T extends UserInfo> T getCurrentUser() {
  Authentication authentication = getAuthentication();

  if (authentication == null) {
   return null;
  }

  Object principal = authentication.getPrincipal();
  if (!(principal instanceof UserInfo)) {
   return null;
  }

  return (T) principal;
 }

 /**
  * 取得当前用户的登录名, 如果当前用户未登录则返回空字符串.
  */
 public static String getCurrentUserName() {
  Authentication authentication = getAuthentication();

  if (authentication == null || authentication.getPrincipal() == null) {
   return "";
  }

  return authentication.getName();
 }
 
 /**
  * 取得当前用户的真实姓名, 如果当前用户未登录则返回空字符串.
  */
 public static String getCurrentName() {
  return getCurrentUser().getName();
 }

 /**
  * 取得当前用户登录IP, 如果当前用户未登录则返回空字符串.
  */
 public static String getCurrentUserIp() {
  Authentication authentication = getAuthentication();

  if (authentication == null) {
   return "";
  }

  Object details = authentication.getDetails();
  if (!(details instanceof WebAuthenticationDetails)) {
   return "";
  }

  WebAuthenticationDetails webDetails = (WebAuthenticationDetails) details;
  return webDetails.getRemoteAddress();
 }

 /**
  * 判断用户是否拥有角色, 如果用户拥有参数中的任意一个角色则返回true.
  */
 public static boolean hasAnyRole(String... roles) {
  Authentication authentication = getAuthentication();

  if (authentication == null) {
   return false;
  }

  Collection<GrantedAuthority> grantedAuthorityList = authentication
    .getAuthorities();
  for (String role : roles) {
   for (GrantedAuthority authority : grantedAuthorityList) {
    if (role.equals(authority.getAuthority())) {
     return true;
    }
   }
  }

  return false;
 }

 /**
  * 将UserDetails保存到Security Context.
  *
  * @param userDetails
  *            已初始化好的用户信息.
  * @param request
  *            用于获取用户IP地址信息,可为Null.
  */
 public static void saveUserDetailsToContext(UserDetails userDetails,
   HttpServletRequest request) {
  PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(
    userDetails, userDetails.getPassword(), userDetails
      .getAuthorities());

  if (request != null) {
   authentication.setDetails(new WebAuthenticationDetails(request));
  }

  SecurityContextHolder.getContext().setAuthentication(authentication);
 }

 /**
  * 取得Authentication, 如当前SecurityContext为空时返回null.
  */
 private static Authentication getAuthentication() {
  SecurityContext context = SecurityContextHolder.getContext();

  if (context == null) {
   return null;
  }

  return context.getAuthentication();
 }
}


applicationContext-security.xml中的配置
<!-- 认证配置, 使用userDetailsService提供的用户信息 -->
	<s:authentication-manager alias="authenticationManager">
		<s:authentication-provider user-service-ref="userDetailsService">
			<s:password-encoder hash="plaintext" />
		</s:authentication-provider>
	</s:authentication-manager>

	<!-- 项目实现的用户查询服务 -->
	<bean id="userDetailsService" class="org.springside.examples.miniweb.service.account.UserDetailsServiceImpl" />
</beans>
分享到:
评论

相关推荐

    Spring security认证授权

    Spring Security默认的用户实体是`UserDetails`,你可以创建一个自定义的`UserDetails`实现类,比如`SysUserDetails`,并映射到`SysUser`数据库模型。 - 如果需要动态增加数据库表字段,可能需要在应用启动时删除...

    Spring Security 把授权信息写入数据库

    要实现这一目标,首先需要将Spring Security 2.0的库文件添加到项目的类路径中。通常,只需要包括`spring-security-acl`、`spring-security-core`、`spring-security-core-tiger`和`spring-security-taglibs`等核心...

    SpringSecurity笔记2-SpringSecurity命名空间

    - 它还允许自定义权限表达式,例如,`&lt;expression-handler&gt;`元素可以配置自定义的Spring Expression Language (SpEL)表达式处理器,扩展Spring Security的默认行为。 3. **Spring Security与SpEL的集成**: - ...

    初识 Spring Security - v1.1.pdf

    - **相关接口和实现类**:Spring Security 提供了一系列接口和实现类来支持Remember-Me功能。 ##### 13. **Session 管理** - **概念**:Spring Security 提供了丰富的session管理机制,包括检测session超时、并发...

    SpringMVC集成SpringSecurity

    5. **SpringSecurity配置**:在SpringSecurity配置文件中,我们需要定义`&lt;http&gt;`元素来配置URL保护策略,`&lt;authentication-manager&gt;`元素来定义认证机制,例如使用`&lt;user-service&gt;`元素配置内存中的用户信息。...

    spring security 3 多页面登录 小秘密小运气

    Spring Security允许通过扩展`AuthenticationProvider`来实现自定义的身份验证逻辑。例如,你可能需要根据不同的登录页面执行不同的验证规则,或者从不同的数据源获取用户信息。 3. **定制错误处理**: 如果登录...

    Spring Security 新手入门级maven实例

    在Spring Security中,我们通常会创建一个配置类,扩展`WebSecurityConfigurerAdapter`。在这个类中,你可以自定义认证(Authentication)和授权(Authorization)规则。例如: ```java @Configuration @...

    spring security 2 配置说明

    Spring Security 2的核心目标是提供一个强大的、可扩展的安全框架,用于Web应用程序的安全性管理。 ### 默认的表结构 在Spring Security 2中,虽然示例中提到的是Oracle 9i数据库,但Spring Security支持多种...

    Spring Security3.1实例

    Spring Security 是一个强大的安全框架,用于Java应用的安全管理。它提供了认证、授权和访问控制功能,使得开发者可以轻松地在应用程序中实现复杂的安全需求。在3.1版本中,Spring Security 进一步优化了其核心架构...

    spring security2配置

    2. **Web安全配置**:创建一个扩展自`WebSecurityConfigurerAdapter`的配置类。在这里,我们可以定制安全规则,比如哪些URL需要被保护,哪些可以公开访问。 3. **用户认证**:配置`UserDetailsService`,这个接口...

    Spring Security使用手册

    在配置方面,Spring Security支持传统的配置方式,即通过XML或Java配置类进行详细配置,同时也支持使用命名空间进行快速配置,这种方式可以简化配置过程,使得安全配置更加简洁明了。使用命名空间配置,可以在`...

    spring security权限管理

    因此,`MyUserDetails.java`可能是实现了`UserDetails`的类,它扩展了用户实体类,添加了Spring Security所需的特性和方法,例如`getAuthorities()`用于获取用户的权限信息。 `applicationContext_security.xml`是...

    Spring Security 基于数据库的权限管理配置

    在基于数据库的权限管理配置中,Spring Security 允许我们存储、管理和验证用户的访问权限,这使得权限控制更加灵活和可扩展。下面将详细阐述如何进行Spring Security的数据库权限管理配置。 1. **配置数据源** 在...

    spring security 培训ppt

    ### Spring Security 概述 Spring Security 是一个强大的且高度可定制的身份验证和访问控制...同时,Spring Security 的灵活性也使得开发者可以根据具体的应用场景选择合适的配置和扩展,从而满足各种复杂的安全需求。

    SpringBoot集成Spring Security实现角色继承【完整源码+数据库】

    在Spring Security中,角色继承允许我们创建一种层次结构,其中某些角色可以包含或扩展其他角色的权限。例如,我们可以定义一个"管理员"角色,它包含"用户"角色的所有权限,并可能有额外的特权。要实现角色继承,...

    myeclipse 8.5的spring security 2.0.5的简单练习(图解)

    ### MyEclipse 8.5 中 Spring Security 2.0.5 的简易实践 #### 一、背景介绍 本篇文章将详细介绍如何在 MyEclipse 8.5 中使用 Spring Security 2.0.5 来实现一个简单的权限管理示例。Spring Security 是一个功能...

    2016 page220 Spring Security Essentials - Nanda Nachimuthu.pdf )

    Spring Security设计时考虑到了灵活性和可扩展性,允许开发者通过添加自定义过滤器、认证提供者等来扩展其核心功能。同时,Spring Security可以轻松地与其他Spring项目集成,比如与Spring MVC和Spring Boot无缝集成...

    SpringSecurity 3配置文件

    - Spring Security允许开发人员通过自定义bean进行扩展,比如自定义认证Provider、权限表达式解析器等。这提供了极大的灵活性,可以根据实际需求定制安全功能。 6. **与其他Spring技术集成** - Spring Security...

    spring security 与ssm框架整合的一个小 demo

    在这个Demo中,你可能会看到更多细节,如登录失败处理器、自定义认证过滤器等,这些都是Spring Security提供的一些高级特性,可以根据实际需求进行配置和扩展。通过这种方式,你可以为你的SSM应用构建一个安全的登录...

Global site tag (gtag.js) - Google Analytics