天天看點

spring security 粗識

最近才開始接觸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;

否則的話,會傳回相對應的錯誤資訊,如剛才寫的抛出新的異常,就是頁面顯示的資訊,具體的方案還是參考上面。

先寫到這裡儲存一下,後續再繼續更新修改一下。。。