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;

否则的话,会返回相对应的错误信息,如刚才写的抛出新的异常,就是页面显示的信息,具体的方案还是参考上面。

先写到这里保存一下,后续再继续更新修改一下。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值