安全管理三

本篇主要讲自定义用户认证与授权

 

在安全管理二中我们实现了自定义数据表实现了用户权限管理,但我们发现,认证与授权的sql写死在了配置文件中,而且字段有限,现实开发中,我们的用户信息需要更多的字段,很明显,这种写死在配置文件中的认证与授权严重不满足我们的需求,我们需要通过自定义用户认证与授权来完成更灵活,更有效的用户权限管理。在spring security中我们需要通过扩展userDetails,以及编写自己的userDetailsService来实现自定义用户认证与授权

 

第一步:扩展userDetails

 

package com.longzhun.fpm.security;

import org.apache.commons.lang.StringUtils;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.userdetails.UserDetails;

public class BaseUserDetails implements UserDetails {
	
	//账号
	protected String username;
	//密码
	protected String password;
	//是否可用
	protected boolean enabled;
	//用户权限集合
	protected GrantedAuthority[] authorties;
	//账号是否过期
	protected boolean accountNonExpired;
	//账号是否被锁
	protected boolean accountNonLocked;
	//密码是否过期
	protected boolean credentialsNonExpired;
	
	public BaseUserDetails(String username, String password, boolean enabled,
			GrantedAuthority[] authorties) {
		this(username,password,enabled,authorties,true,true,true);
	}

	public BaseUserDetails(String username, String password, boolean enabled,
			GrantedAuthority[] authorties, boolean accountNonExpired,
			boolean accountNonLocked, boolean credentialsNonExpired) {
		if(StringUtils.isBlank(username) || StringUtils.isBlank(password)){
			throw new IllegalArgumentException("不允许用户帐号或者密码为空!");
		}
		this.username = username;
		this.password = password;
		this.enabled = enabled;
		this.authorties = authorties;
		this.accountNonExpired = accountNonExpired;
		this.accountNonLocked = accountNonLocked;
		this.credentialsNonExpired = credentialsNonExpired;
	}

	public GrantedAuthority[] getAuthorities() {
		return this.authorties;
	}

	public String getPassword() {
		return this.password;
	}

	public String getUsername() {
		return this.username;
	}

	public boolean isAccountNonExpired() {
		return this.accountNonExpired;
	}

	public boolean isAccountNonLocked() {
		return this.accountNonLocked;
	}

	public boolean isCredentialsNonExpired() {
		return this.credentialsNonExpired;
	}

	public boolean isEnabled() {
		return this.enabled;
	}

}

 

 

第二步:新建用户信息扩展类UserInfo

          目前咱们就用了一个扩展字段Id

 

package com.longzhun.fpm.security;

import org.springframework.security.GrantedAuthority;

public class UserInfo extends BaseUserDetails {

	private String id;
	
	public UserInfo(String username, String password, boolean enabled,
			GrantedAuthority[] authorties) {
		super(username, password, enabled, authorties);
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	
}

 

 第三步:为了更好的与数据库建立映射关系,实现dao与service 方法

 我新建了一个bean  

package com.longzhun.fpm.security;

import java.util.HashSet;
import java.util.Set;

import com.longzhun.fpm.dto.Authority;

public class Security {
	
	private String id;
	
	private String username;
	
	private String password;
	
	private boolean enabled;
	
	
	private Set<Authority> authories = new HashSet<Authority>(0);

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public boolean isEnabled() {
		return enabled;
	}

	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
	}

	public Set<Authority> getAuthories() {
		return authories;
	}

	public void setAuthories(Set<Authority> authories) {
		this.authories = authories;
	}

	

}

 

 

 

第四步:编写自己的userDetailsService实现类

package com.longzhun.fpm.security.service.impl;

import java.util.HashSet;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import com.longzhun.fpm.dto.Authority;
import com.longzhun.fpm.security.Security;
import com.longzhun.fpm.security.UserInfo;
import com.longzhun.fpm.security.dao.SecurityDao;

@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {

	@Autowired
	@Qualifier("securityDao")
	private SecurityDao securityDao;
	
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException, DataAccessException {
		
		Security security = securityDao.getUserInfoByUsername(username);
		if(security == null){
			throw new UsernameNotFoundException("用户 : "+username+"不存在!");
		}
		
		UserInfo userInfo = new UserInfo(username, security.getPassword(),security.isEnabled(), getGrantedAuthorities(security));
		userInfo.setId(security.getId());
		
		
		return userInfo;
	}
	private GrantedAuthority [] getGrantedAuthorities(Security security){
		
		Set<GrantedAuthority> auths = new HashSet<GrantedAuthority>();
		for(Authority authority:security.getAuthories()){
			auths.add(new GrantedAuthorityImpl(authority.getValue()));
		}
		return auths.toArray(new GrantedAuthority[auths.size()]);
	}
}

 

第五步:修改applicationContext-security.xml

将安全管理二写的:

<ss:authentication-provider>
		<ss:password-encoder hash="md5">
			<ss:salt-source user-property="username"/>   盐值    密码+用户名=密码 
		</ss:password-encoder>
		<ss:jdbc-user-service data-source-ref="dataSource"
		users-by-username-query="select username,password,enabled from test_user where username=?"
		authorities-by-username-query="select u.username,r.role_name authority from test_user u
     join test_user_role ur on u.id = ur.user_id
     join test_role r on r.id = ur.role_id
     where u.username =?"/>
	</ss:authentication-provider>

 

替换成:

<ss:authentication-provider user-service-ref="userDetailsService"></ss:authentication-provider>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值