spring security 3 自定义(一)

如果你没有用过自定义的验证的话,你的资源和资源应该有的权限都应该还是在配置文件中配置的。

类似这样:

1.

复制代码
    <http auto-config="true" lowercase-comparisons="false">
        <intercept-url pattern="/images/**" filters="none"/>
        <intercept-url pattern="/styles/**" filters="none"/>
        <intercept-url pattern="/scripts/**" filters="none"/>
        <intercept-url pattern="/app/admin/**" access="ROLE_ADMIN"/>
        <intercept-url pattern="/app/passwordHint*" access="ROLE_ANONYMOUS,ROLE_ADMIN,ROLE_USER"/>
        <intercept-url pattern="/app/signup*" access="ROLE_ANONYMOUS,ROLE_ADMIN,ROLE_USER"/>
        <intercept-url pattern="/app/**" access="ROLE_ADMIN,ROLE_USER"/>
        <form-login login-page="/login" authentication-failure-url="/login?error=true" login-processing-url="/j_security_check"/>
        <remember-me user-service-ref="sysUserDao" key="e37f4b31-0c45-11dd-bd0b-0800200c9a66"/>
    </http>
复制代码

2.你的用户角色权限也应该像这样,是在配置文件中配置的或者是按照标准的数据库指定到一个数据源。

类似这样:

<authentication-manager> 
    <authentication-provider>   
    <jdbc-user-service data-source-ref="securityDataSource"/> 
    </authentication-provider>
 </authentication-manager>

要做一个自定义的验证过程,就是要替换这些。

  如果要实现自定义的这个过程理论上security第一步是根据你的配置文件去数据库中读取相应的资源和权限的对应关系。但是作为我们用户而言,总是从登陆开始。所以先讲如何替换用户登陆时候的过程。

  在非自定义的情况下,security是这样帮我们去验证的。

  当用户输入用户名密码之后,提交到一个controller去验证,这个验证的过程是:

  先看你的配置文件是直接配置用户名密码在资源文件中或者是在他给你的标准表中(也就是直接指定的datasource)然后进行验证。

   替换用户登陆时候的过程,也就是把这一步换成我们自己写的逻辑,不用框架去提取用户的信息判断。看实现。

       首先建一个实体类,这个实体类呢必须实现UserDetails 接口:

复制代码
package cn.com.xinma.frame.model;

import org.compass.annotations.Searchable;
import org.compass.annotations.SearchableComponent;
import org.compass.annotations.SearchableId;
import org.compass.annotations.SearchableProperty;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;

import javax.xml.bind.annotation.XmlRootElement;

import java.io.Serializable;

/**
 * 系统用户登录信息
 * 
 * @author guolc
 * 
 */
@SuppressWarnings("serial")
@Entity
@Table(name = "sys_user")
@Searchable
@XmlRootElement
public class SysUser extends BaseObject implements Serializable, UserDetails {
    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());
        }
    }

    private static SortedSet<GrantedAuthority> sortAuthorities(
            Collection<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 boolean accountNonExpired;
    private boolean accountNonLocked;
    
    private boolean credentialsNonExpired;
    public void setAuthorities(Set<GrantedAuthority> authorities) {
        this.authorities = authorities;
    }

    private boolean enabled = true;

    // 实现了UserDetails之后的相关变量
    private Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>(0);
    
    private String password;

    private String personId;

    private Set<SysGroupMember> sysGroupMembers = new HashSet<SysGroupMember>(0);

    private Set<SysPmenu> sysPmenus = new HashSet<SysPmenu>(0);

    private Set<SysUserRole> sysUserRoles = new HashSet<SysUserRole>(0);

    private String sysuserIsValid;

    private String sysuserLoginname;

    private String sysuserPassword;

    private String username;

    public SysUser() {

    }

    public SysUser(String userId, String userAccount, String userPassword,
            Boolean enabled, Set<SysUserRole> sysUsersRoleses,
            boolean accountNonExpired, boolean credentialsNonExpired,
            boolean accountNonLocked, Collection<GrantedAuthority> authorities) {

        if (((userAccount == null) || "".equals(userAccount))
                || (userPassword == null)) {
            throw new IllegalArgumentException(
                    "Cannot pass null or empty values to constructor");
        }

        this.personId = userId;
        this.sysuserLoginname = userAccount;

        this.sysuserPassword = userPassword;

        this.sysUserRoles = sysUsersRoleses;
        this.username = userAccount;
        this.password = userPassword;

        this.accountNonExpired = accountNonExpired;
        this.credentialsNonExpired = credentialsNonExpired;
        this.accountNonLocked = accountNonLocked;
        this.authorities = Collections
                .unmodifiableSet(sortAuthorities(authorities));
    }

    public boolean equals(Object o) {
        if (!(o instanceof SysUser) || (o == null)) {
            return false;
        }

        SysUser user = (SysUser) o;

        // 具有的权限。
        if (!authorities.equals(user.authorities)) {
            return false;
        }

        // 通过Spring Security构建一个用户时,用户名和密码不能为空。
        return (this.getPassword().equals(user.getPassword())
                && this.getUsername().equals(user.getUsername())
                && (this.isAccountNonExpired() == user.isAccountNonExpired())
                && (this.isAccountNonLocked() == user.isAccountNonLocked())
                && (this.isCredentialsNonExpired() == user
                        .isCredentialsNonExpired()) && (this.isEnabled() == user
                .isEnabled()));
    }

    @Override
    @Transient
    // @OneToMany
    public Collection<GrantedAuthority> getAuthorities() {
        // TODO Auto-generated method stub
        return this.authorities;
    }

    @Override
    @Transient
    public String getPassword() {
        // TODO Auto-generated method stub
        return this.password;
    }

    @Id
    @SearchableId
    @Column(name = "PERSON_ID", unique = true, nullable = false, length = 20)
    public String getPersonId() {
        return this.personId;
    }

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "sysUser")
    public Set<SysGroupMember> getSysGroupMembers() {
        return this.sysGroupMembers;
    }

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "sysUser")
    public Set<SysPmenu> getSysPmenus() {
        return this.sysPmenus;
    }

    @Column(name = "sysuser_is_valid", nullable = false, length = 6)
    public String getSysuserIsValid() {
        return this.sysuserIsValid;
    }

    @Column(name = "sysuser_loginname", nullable = false, length = 60)
    @SearchableProperty
    public String getSysuserLoginname() {
        return this.sysuserLoginname;
    }

    @Column(name = "sysuser_password", nullable = false, length = 60)
    @SearchableProperty
    public String getSysuserPassword() {
        return this.sysuserPassword;
    }

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "sysUser")
    // @Transient
    public Set<SysUserRole> getSysUserRoles() {
        return this.sysUserRoles;
    }

    @Override
    @Transient
    public String getUsername() {
        // TODO Auto-generated method stub
        return this.username;
    }

    public int hashCode() {
        int result = 0;
        result = (sysuserLoginname != null ? sysuserLoginname.hashCode() : 0);
        result = 31 * result
                + (sysuserPassword != null ? sysuserPassword.hashCode() : 0);
        result = 31 * result
                + (sysuserIsValid != null ? sysuserIsValid.hashCode() : 0);

        return result;
    }

    @Override
    @Transient
    public boolean isAccountNonExpired() {
        // TODO Auto-generated method stub
        return this.accountNonExpired;
    }

    @Override
    @Transient
    public boolean isAccountNonLocked() {
        // TODO Auto-generated method stub
        return this.accountNonLocked;
    }

    @Override
    @Transient
    public boolean isCredentialsNonExpired() {
        // TODO Auto-generated method stub
        return this.credentialsNonExpired;
    }

    @Override
    @Transient
    public boolean isEnabled() {
        
        
        return true;
    }

    public void setAccountNonExpired(boolean accountNonExpired) {
        this.accountNonExpired = accountNonExpired;
    }

    public void setAccountNonLocked(boolean accountNonLocked) {
        this.accountNonLocked = accountNonLocked;
    }

    public void setAuthorities(Collection<GrantedAuthority> authorities) {
        this.authorities = (Set<GrantedAuthority>) authorities;
    }

    public void setCredentialsNonExpired(boolean credentialsNonExpired) {
        this.credentialsNonExpired = credentialsNonExpired;
    }

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

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

    public void setPersonId(String personId) {
        this.personId = personId;
    }

    public void setSysGroupMembers(Set<SysGroupMember> sysGroupMembers) {
        this.sysGroupMembers = sysGroupMembers;
    }

    public void setSysPmenus(Set<SysPmenu> sysPmenus) {
        this.sysPmenus = sysPmenus;
    }

    public void setSysuserIsValid(String sysuserIsValid) {
        this.sysuserIsValid = sysuserIsValid;
    }

    public void setSysuserLoginname(String sysuserLoginname) {
        this.sysuserLoginname = sysuserLoginname;
    }

    public void setSysuserPassword(String sysuserPassword) {
        this.sysuserPassword = sysuserPassword;
    }

    public void setSysUserRoles(Set<SysUserRole> sysUserRoles) {
        this.sysUserRoles = sysUserRoles;
    }

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

    public String toString() {
        StringBuffer sb = new StringBuffer(getClass().getSimpleName());

        sb.append(" [");
        sb.append("personId").append("='").append(getPersonId()).append("', ");
        sb.append("sysuserLoginname").append("='")
                .append(getSysuserLoginname()).append("', ");
        sb.append("sysuserPassword").append("='").append(getSysuserPassword())
                .append("', ");
        sb.append("sysuserIsValid").append("='").append(getSysuserIsValid())
                .append("', ");

        sb.append("]");

        return sb.toString();
    }
    
    

}
复制代码

这个实体类是项目里用的,比较长可能看起来比较复杂,有很多对多的关系等等,做几个说明:对新手来说很重要

首先你实现了这个UserDetails 接口之后 只会有这么几个方法。

复制代码
package cn.com.xinma.frame.model;

import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

public class tt implements UserDetails {

    @Override
    public Collection<GrantedAuthority> getAuthorities() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public String getPassword() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public String getUsername() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public boolean isAccountNonExpired() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean isAccountNonLocked() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean isEnabled() {
        // TODO Auto-generated method stub
        return false;
    }

}
复制代码

这些方法你必须给他正确的返回值就可以了,至于你要定义哪些属性,封装哪些属性,完全可以自己去实现。举个简单的例子。

你数据库里的用户密码字段是pwd 你在上面这个实体类中定义了一个变量是private string pwd; 然后你还封装了这个属性(geter seter)

这样没问题,但是你必须保证重写的那个getPassword方法就是返回的正确的密码值。

 

  第二步 建一个service 实现UserDetailsService接口。

   实现UserDetailsService接口之后只会有一个方法:

复制代码
package cn.com.xinma.frame.model;

import org.springframework.dao.DataAccessException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

public class tt implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String arg0)
            throws UsernameNotFoundException, DataAccessException {
        // TODO Auto-generated method stub
        return null;
    }

}
复制代码

通过一个用户名去获得用户的一个详细信息相信不用我实现给大家看,需要说明的是这边你需要把用户密码也查出来,返回值就是刚才我们所创建的实体类

我给出项目中的实现:

View Code

代码写完也总得配置才会起效

复制代码
    <authentication-manager alias="authenticationManager">
        <authentication-provider user-service-ref="UserDetailsService">
            <!-- 用户密码加密 just like 899312{gaobing} to md5 -->
            <password-encoder ref="MyPasswordEncode">
                <salt-source user-property="username" />
            </password-encoder>
        </authentication-provider>
    </authentication-manager>
复制代码

 红色背景指向的是什么大家想想应该就明白了。

这样完成之后用户提交登陆页面的时候就会进入到这个方法,按照你的逻辑去查询用户的信息,最后返回一个实现了userdetail的对象。

如果你看过之前讲密码加密(盐值加密)的话 应该会继续走到你自己定义的密码编辑器那边。

如果你的登陆未成功 , 或者没有进入到你自定义的密码编辑器中,可能是应为在你的实体类中 ,重写的那些方法没有给正确的值。比如isEnabled() 这个方法如果返回的是false,不可用,当然不会继续去判断密码之类

 

好了就这么多 ,讲了蛮多不正确的欢迎纠正。

<script type="text/javascript"> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值