最近才開始接觸spring security來開發項目,把裡面覺得不太懂的或者有意思的現在大概總結一下,友善以後自己再看,再學習...
①LDAP(輕目錄通路協定),看了看,不是特别懂,在此就不獻醜了,想深入了解還是度娘。
②sitemesh技術的應用,裝飾類的配置檔案decorators.xml,主要的
<!-- 要進行裝飾的頁面-->
<decorator name="main" page="main.jsp">
<pattern>/*</pattern>
</decorator>
<!-- 不需要被裝飾的頁面 -->
<excludes>
<pattern>/login.jsp*</pattern>
</excludes>
③關于spring security 3.1登陸驗證,我從這裡面受益匪淺 http://blog.csdn.net/k10509806/article/details/6436987 ,登陸這塊流程還算是比較詳細的。
④密碼的一些規則:
* At least 8 characters.
至少8個字元
* A minimum of one numeric character.
至少包含一個數字字元
* A minimum of one special character (e.g., @, #, $).
至少包含一個特殊字元 (如, @,#,$)
* A leading and ending alpha character.
以字母為開頭且以字母結束
* contain at least one uppercase letter
密碼至少需要包含一個大寫字母。
* Be unique to the previous 13 passwords.
修改的密碼不能與前13次密碼重複
* Be restricted to one change(s) within a 24 hour period except for one-time-password implementations.
除一次性使用密碼外,24小時内限制隻能改一次密碼
* Not be programmed into "remember password" features, scripts or function keys.
不能把”記住密碼“功能編碼在程式的功能子產品或腳本裡
* User account passwords must be changed every 90 days.
使用者帳号密碼必須每90天修改一次
* Maximum number of 5 consecutive failed login attempts, after which the user's access must be suspended.
在最多連續5次嘗試登入失敗後使用者必須被挂起
* Store and transmit passwords in protected (e.g., encrypted or hashed) form.
存儲和發送密碼要以加密的方式進行
? The storage, display, and printing of passwords must be masked, suppressed, or otherwise obscured
密碼不能以明文存儲,顯示和列印
⑤加密算法
自帶的加密算法:
private MessageDigestPasswordEncoder passwordEncoder;
public void setPasswordEncoder(MessageDigestPasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
passwordRecord.setPassword(passwordEncoder.encodePassword(password,null));
自寫加密算法:
public class DefaultDESedeImpl implements StringEncryptor {
//加密
public String encrypt(String target) {
String encodeString = null;
encodeString = new BASE64Encoder().encode(target.getBytes());
return encodeString;
}
//解密
public String decrypt(String target) {
String decodeString = null;
try {
decodeString = new String(new BASE64Decoder().decodeBuffer(target));
} catch (IOException e) {
e.printStackTrace();
}
return decodeString;
}
}
⑥使用者登陸判斷的思路(這裡面使用者被鎖,是必須要超級使用者來解鎖)
0.判斷該使用者是否已經被挂起,如果被挂起,就不執行。。。
1.根據使用者名去資料庫user表查,沒有 傳回空,不執行操作,有的話
==> 判斷該使用者是否被鎖,如果被鎖,傳回,沒有被鎖,判斷loginservice是否有資料,沒有資料,直接建立,有資料的話--
2.去loginRecord(登陸記錄)表中查相對應的username,如果為空,則直接插入,username,failure_times=1,date = new Date();
3.不為空傳回對應的failure_times和date,failure_times如果為0,failure_times=1,date= new Date();
4.如果failure_times不為空但是new Date>date+5分鐘(5分鐘内連續操作);,failure_times=1,date= new Date();
5.如果new Date<date+5分鐘;failure_times=failure_times+1;将之前取出的時間放入資料庫
6.登陸成功{
将loginRecord表中該使用者名的failure_times清零。
}
==>解鎖的時候應該将loginRecord裡面的對應的使用者failure_times清零.
⑦取WEB-INF下面的properties裡面的内容
public class AppConfigUtil {
public Properties properties;
public String fileName = "config.properties";
public AppConfigUtil() {
try {
properties = new Properties();
String path = this.getClass().getResource("/").getPath();
path = path.substring(1,path.indexOf("classes"));
properties.load(new FileInputStream(path+"app-config.properties"));
} catch (Exception e) {
e.printStackTrace();
}
}
//
public String getValue(String confName) {
if (StringUtils.isEmpty(confName)) {
return "";
} else {
return properties.getProperty(confName);
}
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
這個在測試的時候是可以用的,但是伺服器啟動起來,路徑就會出錯,是以,在伺服器端,如果可以的話,再把request對象傳入,這樣就能取得伺服器端的位址:
public class AppConfigUtil {
public Properties properties;
public AppConfigUtil(HttpServletRequest request) {
try {
String filePath = request.getRealPath("/WEB-INF/config.properties");
properties = new Properties();
InputStream in = new BufferedInputStream(new FileInputStream(filePath));
properties.load(in);
} catch (Exception e) {
e.printStackTrace();
}
}
public String getValue(String confName) {
if (StringUtils.isEmpty(confName)) {
return "";
} else {
return properties.getProperty(confName);
}
}
public void setProperties(Properties properties) {
this.properties = properties;
}
}
⑧自己對登陸這一塊的認識:
login.jsp
<form action="<core:url value="/j_spring_security_check"/>" method="post">
<input name="j_username" type="text" style="width:130px;border:1px solid #9D9D9D"/>
<input name="j_password" type="password" style="width:130px;border:1px solid #9D9D9D"/>
固定的j_username和j_password 通過固定的action傳入/j_spring_security_check,到下面進行判斷
applicationContext-security.xml
<bean id="securityFilter"
class="com.xxx.util.LocaleSaverAuthenticationProcessingFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationSuccessHandler" ref="successHandler" />
<property name="authenticationFailureHandler" ref="failureHandler" />
<property name="filterProcessesUrl" value="/j_spring_security_check" />
</bean>
<bean id="successHandler"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="/home.htm" />
</bean>
<bean id="failureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login.jsp?authfailed=Y" />
</bean>
<bean id="loginService" class="com.xxx.service.login.LoginService">
<property name="loginRecordService" ref="loginRecordService"></property>
<constructor-arg index="0" ref="userService" />(有構造方法這樣寫)
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider
user-service-ref="loginService">
<security:password-encoder ref="passwordEncoder" />
</security:authentication-provider>
</security:authentication-manager>
進入這裡面後,會執行LocaleSaverAuthenticationProcessingFilter的attemptAuthentication方法
Authentication auth = super.attemptAuthentication(request, response);//執行這句的時候會去調用loginService的loadUserByUsername方法(記得裡面調用的其他service的set,get方法,下面的是不完全代碼,隻是一個思路)
public class LoginService implements UserDetailsService,Serializable {
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException, DataAccessException{
user = userService.getUserByName(userName);
if (user == null)
throw new UsernameNotFoundException(userName + " cannot be found!");
}
return new LoginUser(user, sourceSystemID);
}
public class LoginUser implements UserDetails {
private User user;
private Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
}
根據傳回的結果,來進行下一步操作,如果成功,if (auth.isAuthenticated()) {...}return auth;
否則的話,會傳回相對應的錯誤資訊,如剛才寫的抛出新的異常,就是頁面顯示的資訊,具體的方案還是參考上面。
先寫到這裡儲存一下,後續再繼續更新修改一下。。。