spring secrity 自定义验证

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a919423654/article/details/54930131

spring secrity 验证默认是使用username和password。但是我项目的登录是根据用户的   的工号和密码进行验证的,所有 有点不同。


关键点是 自己实现了   myAuthenticationProvider;


<?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.0.xsd  
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd">




<global-method-security pre-post-annotations="enabled" />
<!-- HTTP安全配置 -->
<http auto-config="false" entry-point-ref="authenticationEntryPoint"  access-denied-page="/denied.html">
<intercept-url pattern="/login.html" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/index.html" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/m/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/commons/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/upload/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <intercept-url pattern="/cms/**" access="ROLE_USER"/>
       <!--  <intercept-url pattern="/adminIndex.html" access="ROLE_USER"/> -->
        <intercept-url pattern="/pages/*.html" access="ROLE_USER"/>
       <!--  logout-success-url="/login.html" -->
        <logout logout-url="/j_spring_security_logout" invalidate-session="true" 
            delete-cookies="JSESSIONID" success-handler-ref="myLogoutSuccessHandler"/>
        
        <custom-filter ref="corsFilter" after="PRE_AUTH_FILTER"/>
<custom-filter ref="myLoginFilter" position="FORM_LOGIN_FILTER" />
<custom-filter ref="mySecurityFilter" before="FILTER_SECURITY_INTERCEPTOR" />
</http>

<beans:bean id="corsFilter" class="com.threeti.danfoss.base.filter.SecurityCorsFilter" />

<beans:bean id="sas"
class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
<beans:property name="maximumSessions" value="1"></beans:property>
<beans:property name="exceptionIfMaximumExceeded"
value="true"></beans:property>
<beans:constructor-arg name="sessionRegistry"
ref="sessionRegistry"></beans:constructor-arg>
</beans:bean>

<beans:bean id="sessionRegistry"
class="org.springframework.security.core.session.SessionRegistryImpl"></beans:bean>


<beans:bean id="myLoginFilter"
class="com.threeti.danfoss.base.filter.MyUsernamePasswordAuthenticationFilter">

<beans:property name="authenticationManager" ref="myAuthenticationManager"/>  
        <beans:property name="authenticationFailureHandler" ref="failureHandler"/>  
        <beans:property name="authenticationSuccessHandler" ref="successHandler"/>  
<beans:property name="sessionAuthenticationStrategy"
ref="sas"></beans:property>
</beans:bean>



 
    <beans:bean id="successHandler" class="com.threeti.danfoss.base.handler.MyAuthenticationSuccessHandler">  
        <beans:property name="defaultTargetUrl" value="/pages/menu.html#current/wind/surface/level/anim=off/overlay=misery_index/orthographic=39.08,42.42,294/loc=96.475,39.357" />  
    </beans:bean>  
   
    <beans:bean id="failureHandler" class="com.threeti.danfoss.base.handler.MySimpleUrlAuthenticationFailureHandler">  
        <beans:property name="defaultFailureUrl" value="/index.html"/>  
    </beans:bean> 
    
    <beans:bean id="myLogoutSuccessHandler" class="com.threeti.danfoss.base.handler.MyLogoutSuccessHandler">
        <beans:property name="defaultTargetUrl" value="/login.html"/>
        <!-- 下面的 是通过在url参数进行跳转 -->
        <!-- <property name="targetUrlParameter" value="target-url"/>
      <property name="redirectStrategy" ref="safeRedirectStrategy"/> -->
    </beans:bean> 
    <!-- 安全的RedirectStrategy,主要是判断跳转地址是否在白名单中    public class SafeRedirectStrategy implements RedirectStrategy -->
    <!-- <beans:bean id="safeRedirectStrategy" class="com.snsxiu.job.web.security.SafeRedirectStrategy"/> -->
    
<!-- 1.URL过滤器或方法拦截器:用来拦截URL或者方法资源对其进行验证,其抽象基类为AbstractSecurityInterceptor 
2.资源权限获取器:用来取得访问某个URL或者方法所需要的权限,接口为SecurityMetadataSource 3.访问决策器:用来决定用户是否拥有访问权限的关键类,其接口为AccessDecisionManager 
调用顺序为:AbstractSecurityInterceptor调用SecurityMetadataSource取得资源的所有可访问权限, 然后再调用AccessDecisionManager来实现决策,确定用户是否有权限访问该资源。 -->
<!-- 自定义的filter, 必须包含authenticationManager, accessDecisionManager, securityMetadataSource三个属性 -->
<beans:bean id="mySecurityFilter" class="com.threeti.danfoss.base.security.XaFilterSecurityInterceptor">
<beans:property name="authenticationManager" ref="myAuthenticationManager" />
<beans:property name="accessDecisionManager" ref="myAccessDecisionManager" />
<beans:property name="securityMetadataSource" ref="mySecurityMetadataSource" />
</beans:bean>


<!-- 取HTTP配置中的authenticationManager 设置alias别名 -->
<authentication-manager alias="myAuthenticationManager">
<authentication-provider ref="myAuthenticationProvider"/>
</authentication-manager>




<!-- 用户详细信息管理:数据源、用户缓存(通过数据库管理用户、角色、权限、资源) -->
<beans:bean id="userDetailsManager" class="com.threeti.danfoss.base.security.XaUserDetailsService">
</beans:bean>

<!-- <beans:bean
class="org.springframework.security.authentication.encoding.Md5PasswordEncoder"
id="passwordEncoder">
</beans:bean> -->

<beans:bean id="myAuthenticationProvider" class="com.threeti.danfoss.base.filter.MyAuthenticationProvider">
<!-- <beans:property name="userDetailsService" ref="userDetailsManager"/> -->
<beans:constructor-arg name="userDetailsService" ref="userDetailsManager"/>
<!-- <beans:property name="passwordEncoder" ref="passwordEncoder"/> -->
</beans:bean>


<!-- 访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源。 -->
<beans:bean id="myAccessDecisionManager"
class="com.threeti.danfoss.base.security.XaAccessDecisionManagerService" />




<!-- 资源源数据定义,将所有的资源和权限对应关系建立起来,即定义某一资源可以被哪些角色去访问。 -->
<beans:bean id="mySecurityMetadataSource" init-method="loadResourceDefine"
class="com.threeti.danfoss.base.security.XaSecurityMetadataSourceService">
</beans:bean>

<beans:bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/login.html" />
</beans:bean>


</beans:beans>



这个是我实现的的  myAuthenticationProvider;


package com.threeti.danfoss.base.filter;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;


import com.threeti.danfoss.base.exception.LoginLockException;
import com.threeti.danfoss.base.repository.XaCmsUserRepository;
import com.threeti.danfoss.base.util.MD5Util;


public class MyAuthenticationProvider implements AuthenticationProvider{
@Autowired
XaCmsUserRepository xaCmsUserRepository;
private UserDetailsService userDetailsService;  
    public MyAuthenticationProvider(UserDetailsService userDetailsService) {  
        this.userDetailsService = userDetailsService;  
    }
    
public UserDetailsService getUserDetailsService() {
return userDetailsService;
}


public void setUserDetailsService(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}


@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication;  
        String username = token.getName();  
        //从数据库找到的用户  
        UserDetails userDetails = null;  
        if(username != null) {  
            userDetails = userDetailsService.loadUserByUsername(username);  
        }  
        //XaCmsUser user =xaCmsUserRepository.findByNumberAndPasswordAndStatus(userDetails.getUsername(),
        //MD5Util.getMD5String(userDetails.getPassword()), XaConstant.UserStatus.status_normal);
        if(userDetails == null) {
        throw new LoginLockException("账号或者密码错误"); 
        }
        //数据库用户的密码  
        String password = userDetails.getPassword();  
        //与authentication里面的credentials相比较  
        if(!password.equals(MD5Util.getMD5String((String)token.getCredentials()))) {  
            //throw new BadCredentialsException("Invalid username/password");
            throw new LoginLockException("账号或者密码错误"); 
        }  
        //授权  
        return new UsernamePasswordAuthenticationToken(userDetails, password,userDetails.getAuthorities());  
}


@Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.equals(authentication); 
}

}


我标红色的部分就是关键,在MyAuthenticationProvider  中注入了 UserDetailsService 

,调用了loadUserByUsername(username)方法




package com.threeti.danfoss.base.security;


import java.util.ArrayList;
import java.util.List;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.threeti.danfoss.base.constant.XaConstant;
import com.threeti.danfoss.base.entity.XaCmsUser;
import com.threeti.danfoss.base.exception.LoginLockException;
import com.threeti.danfoss.base.repository.XaCmsUserRepository;
import com.threeti.danfoss.base.util.DateProcessUtil;




/**
 * 登录权限验证service
 * @author zj
 *
 */
@Service("MsUserDetailsService")
public class XaUserDetailsService implements UserDetailsService {
    protected static final String ROLE_PREFIX = "ROLE_";
    protected static final GrantedAuthority DEFAULT_USER_ROLE = new SimpleGrantedAuthority(ROLE_PREFIX + "USER");


@Autowired
XaCmsUserRepository xaCmsUserRepository;


public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
XaUserDetails msUserDetails = new XaUserDetails();
try {
XaCmsUser user;
//List<XaCmsUser> userList = xaCmsUserRepository.findByUserName(new String(username.getBytes("ISO-8859-1"),"UTF-8"));

// 这里也是关键,注意,我这里是通过工号进行查询的
List<XaCmsUser> userList = xaCmsUserRepository.findByNumber(new String(username.getBytes("ISO-8859-1"),"UTF-8"));
if(userList.size() > 0 && userList.get(0).getStatus() == XaConstant.UserStatus.status_lock){
throw new LoginLockException("您输入的账号已被锁定");
}
/*if(userList.size() > 0 && userList.get(0).getIsAdmin() != 1){
throw new LoginAdminException("您的账号不是管理员");
}*/
if(userList.size() > 0 && userList.get(0) != null){
user = userList.get(0);
user.setLastLoginDate(DateProcessUtil.getToday(DateProcessUtil.YYYYMMDDHHMMSS));
xaCmsUserRepository.save(user);
msUserDetails.setUsername(user.getNumber());
msUserDetails.setPassword(user.getPassword());
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
GrantedAuthority authority = new SimpleGrantedAuthority(user.getRole().getRoleName());
authorities.add(authority);
//设置用户oauth通过token访问的权限
authorities.add(DEFAULT_USER_ROLE);
authorities.add(new SimpleGrantedAuthority(ROLE_PREFIX + "UNITY"));
authorities.add(new SimpleGrantedAuthority(ROLE_PREFIX + "MOBILE"));
msUserDetails.setAuthorities(authorities);


//msUserDetails.setToken(TokenCenter.issueToken(user.getUserId()));
}
} catch (Exception e) {
e.printStackTrace();
}
return msUserDetails;
}
}

猜你喜欢

转载自blog.csdn.net/a919423654/article/details/54930131