springboot 2.0 集成 Spring Security進行安全控制

添加依賴

<!-- spring security 權限框架依賴 -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
</dependency>

Spring Security配置

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	
	@Autowired
	private UserDetailsService userDetailsService;

	/**
	 * 授權請求(主要就是靜態界面、下載一些靜態文件)
	 */
	@Override
	public void configure(WebSecurity web) throws Exception {
		web.ignoring().antMatchers("/assets/**");
	}

	/**
	 * 驗證用戶的信息、處理註銷
	 */
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http
        .authorizeRequests()
        	//spring boot監控放行
			.antMatchers("/manage/**").permitAll()
            .antMatchers("/").permitAll()
            // swagger-ui
			.antMatchers("/swagger-ui.html", "/webjars/springfox-swagger-ui/**", "/swagger-resources/**",
					"/v2/api-docs")
			.permitAll()
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .loginPage("/login.xhtml")
            .loginProcessingUrl("/login")
            .successForwardUrl("/index.xhtml")
            .permitAll()
            .and()
        .logout()
        .logoutUrl("/logout")
            .permitAll();
	}

	/**
	 * 全局的用戶校驗
	 */
	@Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
    }

	
}

看到代碼中我使用的是UserDetailsService,這裏具體談一下UserDetailsService。之前我們採用了配置文件的方式從數據庫中讀取用戶進行登錄。雖然該方式的靈活性相較於靜態賬號密碼的方式靈活了許多,但是將數據庫的結構暴露在明顯的位置上,絕對不是一個明智的做法。本文通過Java代碼實現UserDetailsService接口來實現身份認證。

UserDetailsService在身份認證中的作用

	Spring Security中進行身份驗證的是AuthenticationManager接口,ProviderManager是它的一個默認實現,但它並不用來處理身份認證,而是委託給配置好的AuthenticationProvider,每個AuthenticationProvider會輪流檢查身份認證。檢查後或者返回Authentication對象或者拋出異常。
	驗證身份就是加載響應的UserDetails,看看是否和用戶輸入的賬號、密碼、權限等信息匹配。此步驟由實現AuthenticationProvider的DaoAuthenticationProvider(它利用UserDetailsService驗證用戶名、密碼和授權)處理。包含 GrantedAuthority 的 UserDetails對象在構建 Authentication對象時填入數據。
	上圖解釋:

在這裏插入圖片描述
新建CustomUserService類實現UserDetailsService接口

@Service
public class CustomUserService implements UserDetailsService {

	@Autowired
	private UserService userService;

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		User user = userService.getUserByUsername(username);
		if (user == null) {
			throw new UsernameNotFoundException("用戶名不存在");
		}
		if (!user.getStatus()) {
			throw new UsernameNotFoundException("用戶賬號已被刪除");
		}

		return new org.springframework.security.core.userdetails.User(username, user.getPassword(), true, true, true,
				true, getGrantedAuthorities(user));
	}

	private List<GrantedAuthority> getGrantedAuthorities(User user) {

		List<GrantedAuthority> authorities = new ArrayList<>();
		return authorities;
	}

}

UserService 添加一個接口實現方法查詢數據庫:

User getUserByUsername(@RequestParam(name = "username") String username);

上述代碼完成,剩下的就是編寫界面代碼了login.html。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:th="http://www.thymeleaf.org"
	xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head th:include="include/head::head"></head>
<head> 		
<link th:href="@{/assets/pages/css/login.css}" rel="stylesheet" type="text/css" />
</head>
<body class=" login">
    <div class="logo">
    </div>
        <div class="content">
            <form class="login-form" th:action="@{/login}" method="post">
                <h3 class="form-title font-green">登&nbsp;錄</h3>
                <div th:if="${param.error}" class="alert alert-danger ">
                    <button class="close" data-close="alert"></button>
                    <span >用戶名或密碼錯誤</span>
                </div>
                <div class="form-group">
                    <!--ie8, ie9 does not support html5 placeholder, so we just show field title for that-->
                    <label class="control-label visible-ie8 visible-ie9">用戶名</label>
                    <input class="form-control form-control-solid placeholder-no-fix" type="text" autocomplete="off" placeholder="用戶名" name="username" />
                </div>
                <div class="form-group">
                    <label class="control-label visible-ie8 visible-ie9">密碼</label>
                    <input class="form-control form-control-solid placeholder-no-fix" type="password" autocomplete="off" placeholder="密碼" name="password" />
                </div>
                <div class="form-actions">
                    <button type="submit" class="btn green uppercase">登 錄</button>
                </div>
            </form>
        </div>
</body>
</html>

最後就是做成功界面了接口,與界面實現了。

@RestController
public class IndexController extends BaseController {

	@Autowired
	private UserService userService;

	@RequestMapping("index.xhtml")
	public ModelAndView index(HttpServletRequest request) {
		User user = userService.getUserByUsername(getPrincipal());
		setSesionAttribute(request, Constants.SESSION_USER, user);
		return new ModelAndView("index");

	}

	private String getPrincipal() {
		String userName = null;
		Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

		if (principal instanceof UserDetails) {
			userName = ((UserDetails) principal).getUsername();
		} else {
			userName = principal.toString();
		}
		return userName;
	}

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章