最近才开始接触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;
否则的话,会返回相对应的错误信息,如刚才写的抛出新的异常,就是页面显示的信息,具体的方案还是参考上面。
先写到这里保存一下,后续再继续更新修改一下。。。