限制IP
如果有IP訪問限制的要求,可以使用SpringEl表達式描述具體IP或者IP子網(wǎng):
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/assets/**").permitAll()
.antMatchers("/**").access("hasIpAddress('192.168.109.136') and hasRole('USER')")
.and().formLogin().loginPage("/login.jsp").permitAll().loginProcessingUrl("/login")
.and().rememberMe()
.and().csrf().disable();
}
這樣就限制了用戶必須是IP地址為192.168.109.136的用戶才能訪問,此外如果將IP寫為192.168.109.0代表192.168.109.1~192.168.109.255網(wǎng)段可以訪問
修改密碼
用戶有變更密碼的需求,變更密碼一般需要提供用戶原密碼等額外信息,此外還需要重復(fù)輸入密碼,以保證用戶輸入正確等內(nèi)容,這些已經(jīng)超出Spring Security的范圍,其實大家關(guān)心的是如何獲得當(dāng)前已認證的用戶信息,并且能夠修改它的密碼
根據(jù)ch02的講解,Spring Security認證后,當(dāng)前認證用戶被存儲到SecurityContextHolder中,這個類提供了靜態(tài)方法SecurityContextHolder.getContext().getAuthentication()就可以獲得當(dāng)前用戶對象,如果需要修改其密碼,只需要自定義服務(wù),完成修改功能即可。
- 修改WebSecurityConfigurerAdapter,增加用戶信息獲取服務(wù)UserDetailService,該接口是Spring Security用戶獲取用戶信息的接口,擴展該接口可以通過數(shù)據(jù)庫、LDAP等服務(wù)獲取用戶信息,用戶信息以UserDetails表示,通過擴展該接口可以提供額外的用戶信息。
/**
* 定義用戶信息獲取服務(wù)
* 這里使用內(nèi)存方式獲取用戶信息,并添加了一個用戶
*
* @return
*/
@Bean
public UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("user").password("password").roles("USER").build());
return manager;
}
- 用戶修改密碼服務(wù)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
/**
* Description:
* 1.獲取已認證用戶
* 2.獲取用戶管理服務(wù)
* 3.修改密碼
* 4.刷新認證
*
* @param password
* @return
*
* @Author: 瓦力
* @Date: 2017/7/20 14:31
*/
@RequestMapping(value = "/changePassword", method = RequestMethod.POST)
public String changePassword(@RequestParam("password") String password) {
//獲得當(dāng)前用戶
UserDetails principal = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (InMemoryUserDetailsManager.class.isInstance(userDetailsService)) {
InMemoryUserDetailsManager manager = (InMemoryUserDetailsManager) userDetailsService;
manager.changePassword(principal.getPassword(), password);//spring security已實現(xiàn)了密碼修改功能
}
SecurityContextHolder.clearContext();//終止當(dāng)前認證用戶
return "redirect:/index.jsp";
}
}public class UserServiceController {
//獲取用戶信息服務(wù)
@Autowired
UserDetailsService userDetailsService;
/**
* Description:跳轉(zhuǎn)到用戶密碼修改界面
*
* @return
*
* @Author: 瓦力
* @Date: 2017/7/20 14:59
*/
@RequestMapping(value = "/changePassword", method = RequestMethod.GET)
public String changePassword() {
return "redirect:/changePassword.jsp";
}
- 用戶修改密碼界面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Change Password</h2>
<div>
<h2>修改密碼</h2>
<form action="/changePassword" method="post">
<input type="password" name="password" placeholder="Password">
<input type="submit" value="Change Password">
</form>
</div>
</body>
</html>
- index.jsp增加鏈接
<h2>修改密碼</h2>
<a href="/changePassword.jsp">修改密碼</a>
通過以上代碼,就可以實現(xiàn)密碼修改,讀者可以試試,其實以上內(nèi)容與Spring Security的關(guān)系并不大,這章主要是為讀者介紹Spring Security是如何保存認證用戶信息以及如何獲得用戶信息,這兩建立基本概念,為隨后的使用數(shù)據(jù)庫方式獲取用戶信息奠定基礎(chǔ)。
InMemoryUserDetailsManager 實現(xiàn)了UserDetailsManager,UserDetailsManager擴展了UserDetailsService,提供了許多內(nèi)置的用戶管理方法:
/**
* Create a new user with the supplied details.
*/
void createUser(UserDetails user);
/**
* Update the specified user.
*/
void updateUser(UserDetails user);
/**
* Remove the user with the given login name from the system.
*/
void deleteUser(String username);
/**
* Modify the current user's password. This should change the user's password in the
* persistent user repository (datbase, LDAP etc).
*
* @param oldPassword current password (for re-authentication if required)
* @param newPassword the password to change to
*/
void changePassword(String oldPassword, String newPassword);
/**
* Check if a user with the supplied login name exists in the system.
*/
boolean userExists(String username);
借助這些方法,我們可以繼續(xù)完善用戶管理功能
代碼示例https://github.com/wexgundam/spring.security/tree/master/ch04