iT邦幫忙

DAY 25
0

無痛學習SpringMVC與Spring Security系列 第 25

[Security]密碼加密及自訂存取被拒網頁(403)

  • 分享至 

  • xImage
  •  

前天無法註冊新使用者問題已找到,主要是EntityManager跟Transaction沒有設定好,今已可work,另外加入一個enabled欄位,註冊畫面如下,

點選Add後,導向首頁如下

表示註冊後setCurrentUser有生效,使用者在註冊後順便登入。

接著要介紹Spring Security支援的密碼加密,例如MD5, SHA-256等,是透過hashing的方法產生雜湊碼來加密,不過上述提到的兩種加密安全性還是有被破解的風險(這太專業了),對於開發者來說,Spring Security提o.s.s.crypto.bcrypt.BCryptPasswordEncoder物件來加密密碼,原理是除了加原本的密碼做hashing外,另外加入一組salt key,以避免有心人是以Rainbow Table的方式倒推密碼,示意圖如下(擷取自Spring Security 3.1)

要做密碼加密首先,要於SecurityConfig中設定Password Encoder參數,如下,另加入當存取權限不足時,AccessDenied的導向網址,其Code如下:

@EnableWebSecurity //Enable springFliterChain
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
	
	@Autowired
	private DneUserDetailsService dneUserDetailsService;
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		// TODO Auto-generated method stub
		http.
			exceptionHandling()
				.accessDeniedPage("/403") //存取被拒時導往的URL
			.and()
			.authorizeRequests()
				.antMatchers("/resources/**").permitAll() //resource資料夾靜態資料可匿名存取
//				.anyRequest().permitAll()//邏輯有誤,以下規則全不適用
				.antMatchers("/userlist").hasAuthority("ROLE_ADMIN")
				.antMatchers("/dcn/add").hasAuthority("ROLE_ADMIN")//必須是admin才可以存取
				.antMatchers("/dcn/**") //對象為所有網址
				.authenticated() //存取必須通過驗證
			.and()
			.formLogin()
             ......
	

	@Override
	@Autowired
	protected void configure(AuthenticationManagerBuilder auth)
			throws Exception {
		// TODO Auto-generated method stub
		auth 
			.userDetailsService(dneUserDetailsService) //換成userDetailsService
			.passwordEncoder(new BCryptPasswordEncoder()); //密碼加密
			
	}
	
}

另外,在DneUserRepository persist時,必須對原本的密碼以BCryptPasswordEncoder加密,其Code如下:

@Repository
@Transactional
public class DneUserRepositoryImp implements DneUserRepository {
	
	@PersistenceContext
	private EntityManager entityManager;

	@Override
	public void save(DneUser user) {
		// TODO Auto-generated method stub
		PasswordEncoder passwordEncoder= new BCryptPasswordEncoder(); //密碼加密 
		user.setPassword(passwordEncoder.encode(user.getPassword())); //以加密後的密碼覆蓋原輸入的密碼
		entityManager.persist(user); 
	}
	........
}

為了測試加密是否成功以及測試自訂存取被拒,新增兩個RequestMapping, /userlist以及/403,其code如下

@Controller
public class DefaultController {
	
	@Autowired
	private DneUserRepository dneUserRepository;
	
        ......	

	@RequestMapping(value="/userlist", method=RequestMethod.GET)
	public String getUserList(Model model){
		List<DneUser> users=dneUserRepository.findAllUsers(); //取得所有user
		model.addAttribute("users", users);
		return "UserList";
	}
	
	@RequestMapping(value="/403", method=RequestMethod.GET)
	public String showAccessDeniedPage(){
		return "403";
	}
	
}

在剛剛的SecurityConfig中userlist網頁只有Admin可以存取,故以Patrick登入後,若點選User List連結,則出現畫面如下

若改以admin登入,則可以看到所有的使用者,可以看到密碼已被加密

另外順便一提SecurityConfig的antMatchers順序是有關係的,例如如果anyRequest().permitAll()設定在其他規則比較嚴格條件的前面的話,Spring Security判斷符合條件,就不會往下在走,意思是最鬆的規則應該在放在最後面,越是嚴格的規則要放在前面,否則,把下面的程式碼註解拿掉的話,則任何人無須登入即可看到新增DCN號碼,畫面如下

.authorizeRequests()
.antMatchers("/resources/**").permitAll() //resource資料夾靜態資料可匿名存取
//	.anyRequest().permitAll()//邏輯有誤,以下規則全不適用
.antMatchers("/userlist").hasAuthority("ROLE_ADMIN")
.antMatchers("/dcn/add").hasAuthority("ROLE_ADMIN")//必須是admin才可以存取
.antMatchers("/dcn/**") //對象為所有網址
.authenticated() //存取必須通過驗證
.and()
.formLogin()
......

明天繼續介紹對如何Secure Method


上一篇
[Interceptor]應用HandlerInterceptor於評估Controller的Performance
下一篇
[Security]Method-Level Security(I)-@PreAuthorize的使用
系列文
無痛學習SpringMVC與Spring Security31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言