spring-boot集成spring-security較簡潔和實用方案

前端時間公司要作一個新的小產品,突發奇想用了spring-boot加spring-security作了登陸驗證,過程當中總感受晚上的資料很散,索性就整理了一下,固然我感受個人也不全哈哈哈,基本夠用。前端

先從最開始提及,引入maven依賴包寫入pom文件:java

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

 

 

 

因爲此次我使用的是spring-boot 1.3.6版本,因此全部範例都已此版本爲基礎。web

廢話不說,上源碼。spring

如今啓動類同包的地方創建spring security的配置類如:sql

package com.shineyue;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import com.shineyue.security.CustomUserDetailsService;
import com.shineyue.security.ShineyueAuthenticationProvider;
/**
 * 集成spring-security
 * @author zml
 *
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
	@Autowired
	private CustomUserDetailsService customUserDetailsService;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/","/login").permitAll()//1根路徑和/login路徑不攔截
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login") //2登錄頁面
                .defaultSuccessUrl("/home") //3登錄成功轉向該頁面
                .permitAll()
                .and()
                .logout().logoutUrl("/logout").logoutSuccessUrl("/login").invalidateHttpSession(true)
                .permitAll();
    }

    //4
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		
    		auth.authenticationProvider(new ShineyueAuthenticationProvider(customUserDetailsService));
    		auth.eraseCredentials(true);
    }
    //5忽略靜態資源的攔截
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/resources/static/**","/informationFeedback","/js/**","/error");
    }
    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
    	return new BCryptPasswordEncoder(4); 
    }

}

其中的ShineyueAuthenticationProvider是咱們處理登陸信息基本邏輯的地方,代碼:數據庫

package com.shineyue.security;

import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
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 org.springframework.security.core.userdetails.UsernameNotFoundException;

public class ShineyueAuthenticationProvider implements AuthenticationProvider {

	private UserDetailsService userDetailsService;
	
	
	public ShineyueAuthenticationProvider(UserDetailsService userDetailsService){
		this.userDetailsService=userDetailsService;
	}
	
	@Override
	public Authentication authenticate(Authentication authentication)
			throws AuthenticationException {
		UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication;
		UserDetails userDetails =userDetailsService.loadUserByUsername(token.getName());
		if(userDetails.getUsername()==null||userDetails.getUsername().equals("")){
			throw new UsernameNotFoundException("用戶不存在");
		}else if(!userDetails.isEnabled()){
			throw new DisabledException("用戶已被禁用");
		}
		String encryptedPassword = userDetails.getPassword();   // 數據庫用戶的密碼,通常都是加密過的
		String inputPassword = (String) token.getCredentials(); // 用戶輸入的密碼
		if(!encryptedPassword.equals(inputPassword)){
			throw new BadCredentialsException("密碼無效,請從新輸入");
		}
		return new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities());
	}

	@Override
	public boolean supports(Class<?> authentication) {
		// TODO Auto-generated method stub
		return UsernamePasswordAuthenticationToken.class.equals(authentication);
	}

}

 

customUserDetailsService對象是去數據庫查詢登陸信息的具體實現,如代碼:apache

 

package com.shineyue.security;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.impl.SLF4JLogFactory;
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.Component;

import com.shineyue.JkViewWebSocket;
import com.shineyue.calldb.CallDbException;
import com.shineyue.calldb.DbMethod;
import com.shineyue.calldb.sql.NoSuchColumnException;
import com.shineyue.calldb.sql.Row;
import com.shineyue.calldb.sql.UnsupportedConversionException;
import com.shineyue.jkjk.bean.UserInfo;
@Component
public class CustomUserDetailsService implements UserDetailsService {
	
	
	
	
	private static final Log log = SLF4JLogFactory.getLog(CustomUserDetailsService.class);
	/**
	 * arg0 登陸時的用戶名
	 */
	@Resource(name="dbTmpMethod")
	private DbMethod dbTmpMethod;
	@Override
	public UserDetails loadUserByUsername(String arg0)
			throws UsernameNotFoundException {
		System.out.println("arg0"+arg0);
		//在這裏執行查詢邏輯返回用戶信息
		SUser su = new SUser();
		if(dbTmpMethod==null){
			log.error("login error -->dbTmpMethod is null");
		}else{
			UserInfo ui =new UserInfo();
			ui.setName(arg0);
			//這下面的代碼是咱們自定義的數據庫查詢API,你們沒必要使用,使用咱們常見的mybatis便可 將查詢出的信息放入su對象中返回SecurityUser對象
			try {
				List<Row> l =dbTmpMethod.Open("JKJK_COMMON_GET_USERINFO", ui);
				if(l.size()==1){
					su.setDob(new Date());
					su.setEmail("hahah@163.com");
					su.setId(l.get(0).getDefInt("uid"));
					su.setName(l.get(0).getTrimString("name"));
					su.setPassword(l.get(0).getTrimString("password"));
					su.setMianAuth(l.get(0).getTrimString("auth"));
					su.setState(l.get(0).getDefInt("state"));
					String[] jgqx_arr=l.get(0).getTrimString("jgqx").split(",");
					if(jgqx_arr.length>0){
						List<String> l_jgqx=Arrays.asList(jgqx_arr);
						su.setJgqx(l_jgqx);
					}
				}
				
				log.info("login user:"+l.get(0).getTrimString("name"));
			} catch (CallDbException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (NoSuchColumnException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (UnsupportedConversionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			//System.out.println("dbTmpMethod is not null");
		}
		
		
		
		return new SecurityUser(su);
	}

}

 

 

這3個類基本上就是完成登陸的核心,固然咱們還須要一些對於用戶信息進行處理類。mybatis

好比:app

package com.shineyue.security;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class SUser implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -7019867470266738718L;
	private int id;
	private String name;
	private String email;
	private String password;
	private Date dob;
	private String mianAuth;
	private int state;
	private Set<SRole> sRoles = new HashSet<SRole>(0);
	private List<String> jgqx=new ArrayList<String>();
	public SUser(){
		
	}
	
	
	public List<String> getJgqx() {
		return jgqx;
	}
	public void setJgqx(List<String> jgqx) {
		this.jgqx = jgqx;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public Date getDob() {
		return dob;
	}
	public void setDob(Date dob) {
		this.dob = dob;
	}
	public Set<SRole> getsRoles() {
		return sRoles;
	}
	public void setsRoles(Set<SRole> sRoles) {
		this.sRoles = sRoles;
	}
	public static long getSerialversionuid() {
		return serialVersionUID;
	}
	public String getMianAuth() {
		return mianAuth;
	}
	public void setMianAuth(String mianAuth) {
		this.mianAuth = mianAuth;
	}
	public int getState() {
		return state;
	}
	public void setState(int state) {
		this.state = state;
	}
	
}

 

 

 

package com.shineyue.security;

public class SRole {
	private int id;
	private String name;
	private int uid;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getUid() {
		return uid;
	}
	public void setUid(int uid) {
		this.uid = uid;
	}
	
}

 

 

package com.shineyue.security;

import java.util.ArrayList;
import java.util.Collection;

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



public class SecurityUser implements UserDetails {
	private SUser user;
	/**
	 * 
	 */
	private static final long serialVersionUID = -1623385418837308233L;
	public SecurityUser(SUser u){
		this.user=u;
	}

	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
		//放入用戶的權限和角色信息
		SimpleGrantedAuthority authority= new SimpleGrantedAuthority("auth:"+this.user.getMianAuth());
		authorities.add(authority);
		authorities.add(authority1);
		return authorities;
	}

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

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

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

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

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

	@Override
	public boolean isEnabled() {
		if(this.user.getState()==2){
			return false;
		}else{
			return true;
		}
		
	}

}

 

 

而後就是在一個Controller類中寫入login方法用於登陸時信息的返回和狀態更改具體代碼以下:maven

@RequestMapping("login")
	public String login(@RequestParam(value="error", required=false) String error,
            @RequestParam(value="logout", required=false) String logout,HttpServletRequest request, HttpServletResponse response,ModelMap model){
		if (error != null) {
			
			 AuthenticationException ex = (AuthenticationException)request.getSession()
			          .getAttribute("SPRING_SECURITY_LAST_EXCEPTION");
			model.put("error", ex.getMessage());
        } else if (logout != null) {
            model.put("logout", "Logout successful");
        }
		return "login";

	}

 

 

以後就是寫一個登陸頁,別忘了等於的用戶名和密碼控件名詞必須用username和password

相關文章
相關標籤/搜索