spring(20)


>

                </div>
<div style="clear:both"></div><div style="border:solid 1px #ccc; background:#eee; float:left; min-width:200px;padding:4px 10px;"><p style="text-align:right;margin:0;"><span style="float:left;">目录<a href="http://blog.csdn.net/bao19901210/article/details/52574340" title="系统根据文章中H1到H6标签自动生成文章目录">(?)</a></span><a href="#" onclick="javascript:return openct(this);" title="展开">[+]</a></p><ol style="display:none;margin-left:14px;padding-left:14px;line-height:160%;"><li><a href="http://blog.csdn.net/bao19901210/article/details/52574340#t0">最简单配置spring-securityxml实现1</a></li><li><a href="http://blog.csdn.net/bao19901210/article/details/52574340#t1">实现UserDetailsService</a></li><li><a href="http://blog.csdn.net/bao19901210/article/details/52574340#t2">实现动态过滤用户权限</a></li><li><a href="http://blog.csdn.net/bao19901210/article/details/52574340#t3">实现AuthenticationProvider自定义参数验证</a></li></ol></div><div style="clear:both"></div><div id="article_content" class="article_content csdn-tracking-statistics" data-pid="blog" data-mod="popu_307" data-dsm="post" style="overflow: hidden;">
<link rel="stylesheet" href="http://csdnimg.cn/release/phoenix/production/htmledit_views-b569b0e3ef.css">
<div class="htmledit_views">

spring security实现方式大致可以分为这几种:

1.配置文件实现,只需要在配置文件中指定拦截的url所需要权限、配置userDetailsService指定用户名、密码、对应权限,就可以实现。

2.实现UserDetailsService,loadUserByUsername(String userName)方法,根据userName来实现自己的业务逻辑返回UserDetails的实现类,需要自定义User类实现UserDetails,比较重要的方法是getAuthorities(),用来返回该用户所拥有的权限。

3.通过自定义filter重写spring security拦截器,实现动态过滤用户权限。

4.通过自定义filter重写spring security拦截器,实现自定义参数来检验用户,并且过滤权限。

1.最简单配置spring-security.xml,实现1

  1. <beans xmlns="http://www.springframework.org/schema/beans"
  2. xmlns:security="http://www.springframework.org/schema/security"
  3. xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
  6. http://www.springframework.org/schema/security
  7. http://www.springframework.org/schema/security/spring-security-4.0.xsd">
  8. <!-- use-expressions:Spring 表达式语言配置访问控制 -->
  9. <security:http auto-config="true" use-expressions="false">
  10. <!-- 配置权限拦截,访问所有url,都需要用户登录,且拥有ROLE_USER权限 -->
  11. <security:intercept-url pattern="/**" access="ROLE_USER" />
  12. </security:http>
  13. <security:authentication-manager alias="authenticationManager">
  14. <security:authentication-provider>
  15. <!-- 配置默认用户,用户名:admin 密码:123456 拥有权限:ROLE_USER -->
  16. <security:user-service>
  17. <security:user name="admin" password="123456"
  18. authorities="ROLE_USER" />
  19. </security:user-service>
  20. </security:authentication-provider>
  21. </security:authentication-manager>
  22. </beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-4.0.xsd">
&lt;!-- use-expressions:Spring 表达式语言配置访问控制 --&gt;
&lt;security:http auto-config="true" use-expressions="false"&gt;
&lt;!-- 配置权限拦截,访问所有url,都需要用户登录,且拥有ROLE_USER权限 --&gt;
&lt;security:intercept-url pattern="/**" access="ROLE_USER" /&gt; &lt;/security:http&gt; &lt;security:authentication-manager alias="authenticationManager"&gt;
&lt;security:authentication-provider&gt;
&lt;!-- 配置默认用户,用户名:admin 密码:123456 拥有权限:ROLE_USER --&gt;
&lt;security:user-service&gt;
&lt;security:user name="admin" password="123456"
authorities="ROLE_USER" /&gt;
&lt;/security:user-service&gt;
&lt;/security:authentication-provider&gt; &lt;/security:authentication-manager&gt;

</beans>

2.实现UserDetailsService

先整理下spring secruity验证流程:

springSecurity的登录验证是由org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter这个过滤器来完成的,在该类的父类AbstractAuthenticationProcessingFilter中有一个AuthenticationManager接口属性,验证工作主要是通过这个AuthenticationManager接口的实例来完成的。在默认情况下,springSecurity框架会把org.springframework.security.authentication.ProviderManager类的实例注入到该属性

UsernamePasswordAuthenticationFilter的验证过程如下:

1. 首先过滤器会调用自身的attemptAuthentication方法,从request中取出authentication, authentication是在org.springframework.security.web.context.SecurityContextPersistenceFilter过滤器中通过捕获用户提交的登录表单中的内容生成的一个org.springframework.security.core.Authentication接口实例.

2. 拿到authentication对象后,过滤器会调用ProviderManager类的authenticate方法,并传入该对象

3.ProviderManager类的authenticate方法中会调用类中的List<AuthenticationProvider> providers集合中的各个AuthenticationProvider接口实现类中的authenticate(Authentication authentication)方法进行验证,由此可见,真正的验证逻辑是由各个AuthenticationProvider接口实现类来完成的。DaoAuthenticationProvider类是默认情况下注入的一个AuthenticationProvider接口实现类

4.provider的实现类在验证用户时,会调用userDetailsService的实现类的loadUserByUsername方法来获取用户信息,

首先spring-security配置文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans:beans xmlns="http://www.springframework.org/schema/security"
  3. xmlns:beans="http://www.springframework.org/schema/beans"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
  7. http://www.springframework.org/schema/security
  8. http://www.springframework.org/schema/security/spring-security.xsd">
  9. <!--   use-expressions=”true” 需要使用表达式方式来写权限-->
  10. <http auto-config="true"  use-expressions="false">
  11. <!--这是spring 提供的http/https信道安全的这个是重要的!你的请求信道是安全的!-->
  12. <!--
  13. 释放用户登陆page 允许任何人访问该页面 ,IS_AUTHENTICATED_ANONYMOUSLY表示不拦截
  14. 另一种不拦截资源的配置:<http pattern="/login.jsp" security="none">
  15. -->
  16. <intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
  17. <!-- 配置用户正常访问page-->
  18. <intercept-url pattern="/**" access="ROLE_USER"/>
  19. <!-- 自定义用户登陆page default-target-url登陆成功跳转的page ,authentication-failure-url="/login.jsp?error=true"这里是登陆失败跳转的page-->
  20. <form-login login-page="/login.jsp" default-target-url="/jsp/index/main.jsp" authentication-failure-url="/login.jsp?error=true"/>
  21. <!-- 记住密码 -->
  22. <!--         <remember-me key="elim" user-service-ref="securityManager"/> -->
  23. </http>
  24. <authentication-manager alias="authenticationManager">
  25. <!--
  26. authentication-provider 引用UserDetailsService实现类时使用user-service-ref属性,引用authentication实现类时,使用ref属性
  27. 这两个属性的区别在于
  28. ref:直接将ref依赖的bean注入到AuthenticationProvider的providers集合中
  29. user-service-ref:定义DaoAuthenticationProvider的bean注入到AuthenticationProvider的providers集合中,
  30. 并且DaoAuthenticationProvider的变量userDetailsService由user-service-ref依赖的bean注入。
  31. -->
  32. <authentication-provider user-service-ref="msecurityManager">
  33. <!-- 密码加密 -->
  34. <password-encoder ref="myPasswordEncoder"/>
  35. </authentication-provider>
  36. </authentication-manager>
  37. <!-- 实现UserDetailsService -->
  38. <beans:bean id="msecurityManager" class="com.ultrapower.me.util.security.support.SecurityManagerSupport"></beans:bean>
  39. <!-- 密码加密 -->
  40. <beans:bean id="myPasswordEncoder" class="com.ultrapower.me.util.security.MyPasswordEncoder"/>
  41. </beans:beans>
<?xml version="1.0" encoding="UTF-8"?>

<beans:beans xmlns="http://www.springframework.org/schema/security"

xmlns:beans="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-4.3.xsd

http://www.springframework.org/schema/security

http://www.springframework.org/schema/security/spring-security.xsd">

<!-- use-expressions=”true” 需要使用表达式方式来写权限-->

<http auto-config="true" use-expressions="false">

<!--这是spring 提供的http/https信道安全的这个是重要的!你的请求信道是安全的!-->

<!--

释放用户登陆page 允许任何人访问该页面 ,IS_AUTHENTICATED_ANONYMOUSLY表示不拦截

另一种不拦截资源的配置:<http pattern="/login.jsp" security="none">

-->
   &lt;intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/&gt;

    &lt;!-- 配置用户正常访问page--&gt;
&lt;intercept-url pattern="/**" access="ROLE_USER"/&gt; &lt;!-- 自定义用户登陆page default-target-url登陆成功跳转的page ,authentication-failure-url="/login.jsp?error=true"这里是登陆失败跳转的page--&gt;
&lt;form-login login-page="/login.jsp" default-target-url="/jsp/index/main.jsp" authentication-failure-url="/login.jsp?error=true"/&gt;
&lt;!-- 记住密码 --&gt;

<!-- <remember-me key="elim" user-service-ref="securityManager"/> -->

</http>

&lt;authentication-manager alias="authenticationManager"&gt;
&lt;!--
authentication-provider 引用UserDetailsService实现类时使用user-service-ref属性,引用authentication实现类时,使用ref属性
这两个属性的区别在于
ref:直接将ref依赖的bean注入到AuthenticationProvider的providers集合中
user-service-ref:定义DaoAuthenticationProvider的bean注入到AuthenticationProvider的providers集合中,
并且DaoAuthenticationProvider的变量userDetailsService由user-service-ref依赖的bean注入。
--&gt;
&lt;authentication-provider user-service-ref="msecurityManager"&gt;
&lt;!-- 密码加密 --&gt;
&lt;password-encoder ref="myPasswordEncoder"/&gt;
&lt;/authentication-provider&gt;
&lt;/authentication-manager&gt; &lt;!-- 实现UserDetailsService --&gt;
&lt;beans:bean id="msecurityManager" class="com.ultrapower.me.util.security.support.SecurityManagerSupport"&gt;&lt;/beans:bean&gt;
&lt;!-- 密码加密 --&gt;
&lt;beans:bean id="myPasswordEncoder" class="com.ultrapower.me.util.security.MyPasswordEncoder"/&gt;

</beans:beans>

userDetailsService实现:

  1. /**
  2. *
  3. */
  4. package com.ultrapower.me.util.security.support;
  5. import java.util.ArrayList;
  6. import java.util.HashMap;
  7. import java.util.HashSet;
  8. import java.util.List;
  9. import java.util.Map;
  10. import java.util.Set;
  11. import org.apache.commons.logging.Log;
  12. import org.apache.commons.logging.LogFactory;
  13. import org.springframework.dao.DataAccessException;
  14. import org.springframework.jdbc.core.JdbcTemplate;
  15. import org.springframework.security.core.userdetails.UserDetails;
  16. import org.springframework.security.core.userdetails.UserDetailsService;
  17. import org.springframework.security.core.userdetails.UsernameNotFoundException;
  18. import com.ultrapower.me.util.Constants;
  19. import com.ultrapower.me.util.dbDao.SpringBeanUtil;
  20. import com.ultrapower.me.util.security.SecurityManager;
  21. import com.ultrapower.me.util.security.entity.Resource;
  22. import com.ultrapower.me.util.security.entity.Role;
  23. import com.ultrapower.me.util.security.entity.User;
  24. import com.ultrapower.me.util.task.PasswordUtils;
  25. public class SecurityManagerSupport  implements UserDetailsService{
  26. private   Log   log   = LogFactory.getLog(this.getClass().getName());
  27. public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException, DataAccessException {
  28. //        List<User> users = getHibernateTemplate().find("FROM User user WHERE user.name = ? AND user.disabled = false", userName);
  29. log.info("SecurityManagerSupport.loadUserByUsername.userName:"+userName);
  30. User user =null;
  31. if("admin".equals(userName)){
  32. Set<Role> roles = new HashSet<Role>() ;
  33. Role role = new Role();
  34. role.setRoleid("ROLE_USER");
  35. role.setRoleName("ROLE_USER");
  36. Set<Resource> resources=new HashSet<Resource>() ;
  37. Resource res = new Resource();
  38. res.setResid("ME001");
  39. res.setResName("首页");
  40. res.setResUrl("/jsp/index/main.jsp");
  41. res.setType("ROLE_USER");
  42. res.setRoles(roles);
  43. resources.add(res);
  44. role.setResources(resources);
  45. roles.add(role);
  46. user = new User();
  47. user.setAccount("admin");
  48. user.setDisabled(false);
  49. user.setPassword(PasswordUtils.entryptPassword(Constants.securityKey));
  50. log.info(user.getPassword());
  51. user.setRoles(roles);
  52. }
  53. return user;//返回UserDetails的实现user不为空,则验证通过
  54. }
  55. }
/**
*
*/
package com.ultrapower.me.util.security.support; import java.util.ArrayList;

import java.util.HashMap;

import java.util.HashSet;

import java.util.List;

import java.util.Map;

import java.util.Set; import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.springframework.dao.DataAccessException;

import org.springframework.jdbc.core.JdbcTemplate;

import org.springframework.security.core.userdetails.UserDetails;

import org.springframework.security.core.userdetails.UserDetailsService;

import org.springframework.security.core.userdetails.UsernameNotFoundException; import com.ultrapower.me.util.Constants;

import com.ultrapower.me.util.dbDao.SpringBeanUtil;

import com.ultrapower.me.util.security.SecurityManager;

import com.ultrapower.me.util.security.entity.Resource;

import com.ultrapower.me.util.security.entity.Role;

import com.ultrapower.me.util.security.entity.User;

import com.ultrapower.me.util.task.PasswordUtils; public class SecurityManagerSupport implements UserDetailsService{

private Log log = LogFactory.getLog(this.getClass().getName());
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException, DataAccessException {

// List<User> users = getHibernateTemplate().find("FROM User user WHERE user.name = ? AND user.disabled = false", userName);

log.info("SecurityManagerSupport.loadUserByUsername.userName:"+userName);

	User user =null;
if("admin".equals(userName)){
Set&lt;Role&gt; roles = new HashSet&lt;Role&gt;() ;
Role role = new Role();
role.setRoleid("ROLE_USER");
role.setRoleName("ROLE_USER"); Set&lt;Resource&gt; resources=new HashSet&lt;Resource&gt;() ; Resource res = new Resource();
res.setResid("ME001");
res.setResName("首页");
res.setResUrl("/jsp/index/main.jsp");
res.setType("ROLE_USER");
res.setRoles(roles);
resources.add(res); role.setResources(resources); roles.add(role);
user = new User();
user.setAccount("admin");
user.setDisabled(false);
user.setPassword(PasswordUtils.entryptPassword(Constants.securityKey));
log.info(user.getPassword());
user.setRoles(roles);
}
return user;//返回UserDetails的实现user不为空,则验证通过
}

}

UserDetails实现:

  1. /**
  2. *
  3. */
  4. package com.ultrapower.me.util.security.entity;
  5. import java.util.ArrayList;
  6. import java.util.Collection;
  7. import java.util.HashMap;
  8. import java.util.List;
  9. import java.util.Map;
  10. import java.util.Set;
  11. import org.apache.commons.lang.StringUtils;
  12. import org.springframework.security.core.GrantedAuthority;
  13. import org.springframework.security.core.authority.SimpleGrantedAuthority;
  14. import org.springframework.security.core.userdetails.UserDetails;
  15. public class User implements UserDetails {
  16. private static final long serialVersionUID = 8026813053768023527L;
  17. private String account;
  18. private String name;
  19. private String password;
  20. private boolean disabled;
  21. private Set<Role> roles;
  22. private Map<String, List<Resource>> roleResources;
  23. /**
  24. * The default constructor
  25. */
  26. public User() {
  27. }
  28. /**
  29. * Returns the authorites string
  30. *
  31. * eg.
  32. *    downpour --- ROLE_ADMIN,ROLE_USER
  33. *    robbin --- ROLE_ADMIN
  34. *
  35. * @return
  36. */
  37. public String getAuthoritiesString() {
  38. List<String> authorities = new ArrayList<String>();
  39. for(GrantedAuthority authority : this.getAuthorities()) {
  40. authorities.add(authority.getAuthority());
  41. }
  42. return StringUtils.join(authorities, ",");
  43. }
  44. @Override
  45. public Collection<? extends GrantedAuthority> getAuthorities() {
  46. // 根据自定义逻辑来返回用户权限,如果用户权限返回空或者和拦截路径对应权限不同,验证不通过
  47. if(!roles.isEmpty()){
  48. List<GrantedAuthority> list = new ArrayList<GrantedAuthority>();
  49. GrantedAuthority au = new SimpleGrantedAuthority("ROLE_USER");
  50. list.add(au);
  51. return list;
  52. }
  53. return null;
  54. }
  55. /*
  56. * 密码
  57. */
  58. public String getPassword() {
  59. return password;
  60. }
  61. /*
  62. * 用户名
  63. */
  64. public String getUsername() {
  65. return name;
  66. }
  67. /*
  68. *帐号是否不过期,false则验证不通过
  69. */
  70. public boolean isAccountNonExpired() {
  71. return true;
  72. }
  73. /*
  74. * 帐号是否不锁定,false则验证不通过
  75. */
  76. public boolean isAccountNonLocked() {
  77. return true;
  78. }
  79. /*
  80. * 凭证是否不过期,false则验证不通过
  81. */
  82. public boolean isCredentialsNonExpired() {
  83. return true;
  84. }
  85. /*
  86. * 该帐号是否启用,false则验证不通过
  87. */
  88. public boolean isEnabled() {
  89. return !disabled;
  90. }
  91. /**
  92. * @return the name
  93. */
  94. public String getName() {
  95. return name;
  96. }
  97. /**
  98. * @return the disabled
  99. */
  100. public boolean isDisabled() {
  101. return disabled;
  102. }
  103. /**
  104. * @return the roles
  105. */
  106. public Set<Role> getRoles() {
  107. return roles;
  108. }
  109. /**
  110. * @return the roleResources
  111. */
  112. public Map<String, List<Resource>> getRoleResources() {
  113. // init roleResources for the first time
  114. System.out.println("---------------------------------------------------");
  115. if(this.roleResources == null) {
  116. this.roleResources = new HashMap<String, List<Resource>>();
  117. for(Role role : this.roles) {
  118. String roleName = role.getRoleName();
  119. Set<Resource> resources = role.getResources();
  120. for(Resource resource : resources) {
  121. String key = roleName + "_" + resource.getType();
  122. if(!this.roleResources.containsKey(key)) {
  123. this.roleResources.put(key, new ArrayList<Resource>());
  124. }
  125. this.roleResources.get(key).add(resource);
  126. }
  127. }
  128. }
  129. return this.roleResources;
  130. }
  131. /**
  132. * @param name the name to set
  133. */
  134. public void setName(String name) {
  135. this.name = name;
  136. }
  137. /**
  138. * @param password the password to set
  139. */
  140. public void setPassword(String password) {
  141. this.password = password;
  142. }
  143. /**
  144. * @param disabled the disabled to set
  145. */
  146. public void setDisabled(boolean disabled) {
  147. this.disabled = disabled;
  148. }
  149. /**
  150. * @param roles the roles to set
  151. */
  152. public void setRoles(Set<Role> roles) {
  153. this.roles = roles;
  154. }
  155. public String getAccount() {
  156. return account;
  157. }
  158. public void setAccount(String account) {
  159. this.account = account;
  160. }
  161. public void setRoleResources(Map<String, List<Resource>> roleResources) {
  162. this.roleResources = roleResources;
  163. }
  164. }
/**
*
*/
package com.ultrapower.me.util.security.entity; import java.util.ArrayList;

import java.util.Collection;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import java.util.Set; import org.apache.commons.lang.StringUtils;

import org.springframework.security.core.GrantedAuthority;

import org.springframework.security.core.authority.SimpleGrantedAuthority;

import org.springframework.security.core.userdetails.UserDetails; public class User implements UserDetails {
private static final long serialVersionUID = 8026813053768023527L;

private String account;

private String name;

private String password;

private boolean disabled;

private Set&lt;Role&gt; roles;

private Map&lt;String, List&lt;Resource&gt;&gt; roleResources;

/**
* The default constructor
*/
public User() { } /**
* Returns the authorites string
*
* eg.
* downpour --- ROLE_ADMIN,ROLE_USER
* robbin --- ROLE_ADMIN
*
* @return
*/
public String getAuthoritiesString() {
List&lt;String&gt; authorities = new ArrayList&lt;String&gt;();
for(GrantedAuthority authority : this.getAuthorities()) {
authorities.add(authority.getAuthority());
}
return StringUtils.join(authorities, ",");
} @Override
public Collection&lt;? extends GrantedAuthority&gt; getAuthorities() {
// 根据自定义逻辑来返回用户权限,如果用户权限返回空或者和拦截路径对应权限不同,验证不通过
if(!roles.isEmpty()){
List&lt;GrantedAuthority&gt; list = new ArrayList&lt;GrantedAuthority&gt;();
GrantedAuthority au = new SimpleGrantedAuthority("ROLE_USER");
list.add(au);
return list;
}
return null;
} /*
* 密码
*/
public String getPassword() {
return password;
} /*
* 用户名
*/
public String getUsername() {
return name;
} /*
*帐号是否不过期,false则验证不通过
*/
public boolean isAccountNonExpired() {
return true;
} /*
* 帐号是否不锁定,false则验证不通过
*/
public boolean isAccountNonLocked() {
return true;
} /*
* 凭证是否不过期,false则验证不通过
*/
public boolean isCredentialsNonExpired() {
return true;
} /*
* 该帐号是否启用,false则验证不通过
*/
public boolean isEnabled() {
return !disabled;
} /**
* @return the name
*/
public String getName() {
return name;
} /**
* @return the disabled
*/
public boolean isDisabled() {
return disabled;
} /**
* @return the roles
*/
public Set&lt;Role&gt; getRoles() {
return roles;
} /**
* @return the roleResources
*/
public Map&lt;String, List&lt;Resource&gt;&gt; getRoleResources() {
// init roleResources for the first time
System.out.println("---------------------------------------------------");
if(this.roleResources == null) { this.roleResources = new HashMap&lt;String, List&lt;Resource&gt;&gt;(); for(Role role : this.roles) {
String roleName = role.getRoleName();
Set&lt;Resource&gt; resources = role.getResources();
for(Resource resource : resources) {
String key = roleName + "_" + resource.getType();
if(!this.roleResources.containsKey(key)) {
this.roleResources.put(key, new ArrayList&lt;Resource&gt;());
}
this.roleResources.get(key).add(resource);
}
} }
return this.roleResources;
} /**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
} /**
* @param password the password to set
*/
public void setPassword(String password) {
this.password = password;
} /**
* @param disabled the disabled to set
*/
public void setDisabled(boolean disabled) {
this.disabled = disabled;
} /**
* @param roles the roles to set
*/
public void setRoles(Set&lt;Role&gt; roles) {
this.roles = roles;
} public String getAccount() {
return account;
} public void setAccount(String account) {
this.account = account;
} public void setRoleResources(Map&lt;String, List&lt;Resource&gt;&gt; roleResources) {
this.roleResources = roleResources;
}

}

3.实现动态过滤用户权限

在spring-security配置文件的http标签中添加如下配置
  1. <custom-filter before="FILTER_SECURITY_INTERCEPTOR" ref="securityInterceptor"/>
<custom-filter before="FILTER_SECURITY_INTERCEPTOR" ref="securityInterceptor"/>

在spring-security配置文件中添加如下配置

  1. <!--     自定义拦截器 -->
  2. <beans:bean id="securityInterceptor" class="com.ultrapower.me.util.security.interceptor.SecurityInterceptor">
  3. <beans:property name="authenticationManager" ref="authenticationManager"/>
  4. <beans:property name="accessDecisionManager" ref="mesecurityAccessDecisionManager"/>
  5. <beans:property name="securityMetadataSource" ref="secureResourceFilterInvocationDefinitionSource" />
  6. </beans:bean>
  7. <!--     获取访问url对应的所有权限 -->
  8. <beans:bean id="secureResourceFilterInvocationDefinitionSource" class="com.ultrapower.me.util.security.interceptor.SecureResourceFilterInvocationDefinitionSource" />
  9. <!--     校验用户的权限是否足够 -->
  10. <beans:bean id="mesecurityAccessDecisionManager" class="com.ultrapower.me.util.security.interceptor.SecurityAccessDecisionManager" />
<!-- 	自定义拦截器 -->
<beans:bean id="securityInterceptor" class="com.ultrapower.me.util.security.interceptor.SecurityInterceptor">
<beans:property name="authenticationManager" ref="authenticationManager"/>
<beans:property name="accessDecisionManager" ref="mesecurityAccessDecisionManager"/>
<beans:property name="securityMetadataSource" ref="secureResourceFilterInvocationDefinitionSource" />
</beans:bean>
<!-- 获取访问url对应的所有权限 -->
<beans:bean id="secureResourceFilterInvocationDefinitionSource" class="com.ultrapower.me.util.security.interceptor.SecureResourceFilterInvocationDefinitionSource" />
<!-- 校验用户的权限是否足够 -->
<beans:bean id="mesecurityAccessDecisionManager" class="com.ultrapower.me.util.security.interceptor.SecurityAccessDecisionManager" />



securityInterceptor继承AbstractSecurityInterceptor过滤器,实现Filter过滤器
  1. package com.ultrapower.me.util.security.interceptor;
  2. import java.io.IOException;
  3. import javax.servlet.Filter;
  4. import javax.servlet.FilterChain;
  5. import javax.servlet.FilterConfig;
  6. import javax.servlet.ServletException;
  7. import javax.servlet.ServletRequest;
  8. import javax.servlet.ServletResponse;
  9. import org.springframework.security.access.SecurityMetadataSource;
  10. import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
  11. import org.springframework.security.access.intercept.InterceptorStatusToken;
  12. import org.springframework.security.web.FilterInvocation;
  13. import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
  14. public class SecurityInterceptor extends AbstractSecurityInterceptor implements Filter{
  15. //配置文件注入
  16. private FilterInvocationSecurityMetadataSource securityMetadataSource;
  17. public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
  18. return securityMetadataSource;
  19. }
  20. public void setSecurityMetadataSource(
  21. FilterInvocationSecurityMetadataSource securityMetadataSource) {
  22. this.securityMetadataSource = securityMetadataSource;
  23. }
  24. @Override
  25. public void doFilter(ServletRequest request, ServletResponse response,
  26. FilterChain chain) throws IOException, ServletException {
  27. // TODO Auto-generated method stub\
  28. FilterInvocation fi = new FilterInvocation(request, response, chain);
  29. //fi里面有一个被拦截的url
  30. //里面调用MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限
  31. //再调用MyAccessDecisionManager的decide方法来校验用户的权限是否足够
  32. InterceptorStatusToken token = super.beforeInvocation(fi);
  33. try {
  34. //执行下一个拦截器
  35. fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
  36. } finally {
  37. super.afterInvocation(token, null);
  38. }
  39. }
  40. @Override
  41. public void init(FilterConfig arg0) throws ServletException {
  42. // TODO Auto-generated method stub
  43. }
  44. @Override
  45. public Class<?> getSecureObjectClass() {
  46. // TODO Auto-generated method stub
  47. return FilterInvocation.class;
  48. }
  49. @Override
  50. public SecurityMetadataSource obtainSecurityMetadataSource() {
  51. // TODO Auto-generated method stub
  52. return this.securityMetadataSource;
  53. }
  54. @Override
  55. public void destroy() {
  56. // TODO Auto-generated method stub
  57. }
  58. }
package com.ultrapower.me.util.security.interceptor;

import java.io.IOException;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse; import org.springframework.security.access.SecurityMetadataSource;

import org.springframework.security.access.intercept.AbstractSecurityInterceptor;

import org.springframework.security.access.intercept.InterceptorStatusToken;

import org.springframework.security.web.FilterInvocation;

import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; public class SecurityInterceptor extends AbstractSecurityInterceptor implements Filter{
//配置文件注入
private FilterInvocationSecurityMetadataSource securityMetadataSource; public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
return securityMetadataSource;
} public void setSecurityMetadataSource(
FilterInvocationSecurityMetadataSource securityMetadataSource) {
this.securityMetadataSource = securityMetadataSource;
} @Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub\ FilterInvocation fi = new FilterInvocation(request, response, chain);
//fi里面有一个被拦截的url
//里面调用MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限
//再调用MyAccessDecisionManager的decide方法来校验用户的权限是否足够
InterceptorStatusToken token = super.beforeInvocation(fi);
try {
//执行下一个拦截器
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} finally {
super.afterInvocation(token, null);
} } @Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub } @Override
public Class&lt;?&gt; getSecureObjectClass() {
// TODO Auto-generated method stub
return FilterInvocation.class;
} @Override
public SecurityMetadataSource obtainSecurityMetadataSource() {
// TODO Auto-generated method stub
return this.securityMetadataSource;
} @Override
public void destroy() {
// TODO Auto-generated method stub
}

}

登陆后,每次访问资源都会被这个拦截器拦截,会执行doFilter这个方法,这个方法调用了invoke方法,其中fi断点显示是一个url(可能重写了toString方法吧,但是里面还有一些方法的),最重要的是beforeInvocation这个方法,它首先会调用MyInvocationSecurityMetadataSource类的getAttributes方法获取被拦截url所需的权限,在调用MyAccessDecisionManager类decide方法判断用户是否够权限。弄完这一切就会执行下一个拦截器。


secureResourceFilterInvocationDefinitionSource实现
  1. /**
  2. *
  3. */
  4. package com.ultrapower.me.util.security.interceptor;
  5. import java.util.ArrayList;
  6. import java.util.Collection;
  7. import java.util.HashMap;
  8. import java.util.Iterator;
  9. import java.util.Map;
  10. import javax.servlet.ServletContext;
  11. import org.springframework.beans.factory.InitializingBean;
  12. import org.springframework.security.access.ConfigAttribute;
  13. import org.springframework.security.access.SecurityConfig;
  14. import org.springframework.security.web.FilterInvocation;
  15. import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
  16. import org.springframework.util.AntPathMatcher;
  17. import org.springframework.util.PathMatcher;
  18. public class SecureResourceFilterInvocationDefinitionSource implements FilterInvocationSecurityMetadataSource, InitializingBean {
  19. private PathMatcher matcher;
  20. private static Map<String, Collection<ConfigAttribute>> map = new HashMap<String, Collection<ConfigAttribute>>();
  21. /*
  22. * 初始化用户权限,为了简便操作没有从数据库获取
  23. * 实际操作可以从数据库中获取所有资源路径url所对应的权限
  24. */
  25. public void afterPropertiesSet() throws Exception {
  26. this.matcher = new AntPathMatcher();//用来匹配访问资源路径
  27. Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
  28. ConfigAttribute ca = new SecurityConfig("ROLE_USER");
  29. atts.add(ca);
  30. map.put("/jsp/index/main.jsp", atts);
  31. Collection<ConfigAttribute> attsno =new ArrayList<ConfigAttribute>();
  32. ConfigAttribute cano = new SecurityConfig("ROLE_NO");
  33. attsno.add(cano);
  34. map.put("/http://blog.csdn.net/u012367513/article/details/other.jsp", attsno);
  35. }
  36. @Override
  37. public Collection<ConfigAttribute> getAttributes(Object object)
  38. throws IllegalArgumentException {
  39. // TODO Auto-generated method stub
  40. FilterInvocation filterInvocation = (FilterInvocation) object;
  41. String requestURI = filterInvocation.getRequestUrl();
  42. //循环资源路径,当访问的Url和资源路径url匹配时,返回该Url所需要的权限
  43. for(Iterator<Map.Entry<String, Collection<ConfigAttribute>>> iter = map.entrySet().iterator(); iter.hasNext();) {
  44. Map.Entry<String, Collection<ConfigAttribute>> entry = iter.next();
  45. String url = entry.getKey();
  46. if(matcher.match(url, requestURI)) {
  47. return map.get(requestURI);
  48. }
  49. }
  50. return null;
  51. }
  52. @Override
  53. public Collection<ConfigAttribute> getAllConfigAttributes() {
  54. // TODO Auto-generated method stub
  55. return null;
  56. }
  57. /* (non-Javadoc)
  58. * @see org.springframework.security.intercept.ObjectDefinitionSource#getConfigAttributeDefinitions()
  59. */
  60. @SuppressWarnings("rawtypes")
  61. public Collection getConfigAttributeDefinitions() {
  62. return null;
  63. }
  64. /* (non-Javadoc)
  65. * @see org.springframework.security.intercept.ObjectDefinitionSource#supports(java.lang.Class)
  66. */
  67. public boolean supports(@SuppressWarnings("rawtypes") Class clazz) {
  68. return true;
  69. }
  70. /**
  71. *
  72. * @param filterInvocation
  73. * @return
  74. */
  75. @SuppressWarnings("unchecked")
  76. private Map<String, String> getUrlAuthorities(org.springframework.security.web.FilterInvocation filterInvocation) {
  77. ServletContext servletContext = filterInvocation.getHttpRequest().getSession().getServletContext();
  78. return (Map<String, String>)servletContext.getAttribute("urlAuthorities");
  79. }
  80. }
/**
*
*/
package com.ultrapower.me.util.security.interceptor; import java.util.ArrayList;

import java.util.Collection;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map; import javax.servlet.ServletContext; import org.springframework.beans.factory.InitializingBean;

import org.springframework.security.access.ConfigAttribute;

import org.springframework.security.access.SecurityConfig;

import org.springframework.security.web.FilterInvocation;

import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

import org.springframework.util.AntPathMatcher;

import org.springframework.util.PathMatcher; public class SecureResourceFilterInvocationDefinitionSource implements FilterInvocationSecurityMetadataSource, InitializingBean {
private PathMatcher matcher;

private static Map&lt;String, Collection&lt;ConfigAttribute&gt;&gt; map = new HashMap&lt;String, Collection&lt;ConfigAttribute&gt;&gt;();

/*
* 初始化用户权限,为了简便操作没有从数据库获取
* 实际操作可以从数据库中获取所有资源路径url所对应的权限
*/
public void afterPropertiesSet() throws Exception {
this.matcher = new AntPathMatcher();//用来匹配访问资源路径
Collection&lt;ConfigAttribute&gt; atts = new ArrayList&lt;ConfigAttribute&gt;();
ConfigAttribute ca = new SecurityConfig("ROLE_USER");
atts.add(ca);
map.put("/jsp/index/main.jsp", atts);
Collection&lt;ConfigAttribute&gt; attsno =new ArrayList&lt;ConfigAttribute&gt;();
ConfigAttribute cano = new SecurityConfig("ROLE_NO");
attsno.add(cano);
map.put("/http://blog.csdn.net/u012367513/article/details/other.jsp", attsno);
} @Override
public Collection&lt;ConfigAttribute&gt; getAttributes(Object object)
throws IllegalArgumentException {
// TODO Auto-generated method stub
FilterInvocation filterInvocation = (FilterInvocation) object; String requestURI = filterInvocation.getRequestUrl();
//循环资源路径,当访问的Url和资源路径url匹配时,返回该Url所需要的权限
for(Iterator&lt;Map.Entry&lt;String, Collection&lt;ConfigAttribute&gt;&gt;&gt; iter = map.entrySet().iterator(); iter.hasNext();) {
Map.Entry&lt;String, Collection&lt;ConfigAttribute&gt;&gt; entry = iter.next();
String url = entry.getKey(); if(matcher.match(url, requestURI)) {
return map.get(requestURI);
}
} return null;
} @Override
public Collection&lt;ConfigAttribute&gt; getAllConfigAttributes() {
// TODO Auto-generated method stub
return null;
} /* (non-Javadoc)
* @see org.springframework.security.intercept.ObjectDefinitionSource#getConfigAttributeDefinitions()
*/
@SuppressWarnings("rawtypes")
public Collection getConfigAttributeDefinitions() {
return null;
} /* (non-Javadoc)
* @see org.springframework.security.intercept.ObjectDefinitionSource#supports(java.lang.Class)
*/
public boolean supports(@SuppressWarnings("rawtypes") Class clazz) {
return true;
} /**
*
* @param filterInvocation
* @return
*/
@SuppressWarnings("unchecked")
private Map&lt;String, String&gt; getUrlAuthorities(org.springframework.security.web.FilterInvocation filterInvocation) {
ServletContext servletContext = filterInvocation.getHttpRequest().getSession().getServletContext();
return (Map&lt;String, String&gt;)servletContext.getAttribute("urlAuthorities");
}

}

mesecurityAccessDecisionManager实现

  1. package com.ultrapower.me.util.security.interceptor;
  2. import java.util.Collection;
  3. import java.util.Iterator;
  4. import org.springframework.security.access.AccessDecisionManager;
  5. import org.springframework.security.access.AccessDeniedException;
  6. import org.springframework.security.access.ConfigAttribute;
  7. import org.springframework.security.access.SecurityConfig;
  8. import org.springframework.security.authentication.InsufficientAuthenticationException;
  9. import org.springframework.security.core.Authentication;
  10. import org.springframework.security.core.GrantedAuthority;
  11. public class SecurityAccessDecisionManager implements AccessDecisionManager {
  12. /**
  13. * 检查用户是否够权限访问资源
  14. * authentication 是从spring的全局缓存SecurityContextHolder中拿到的,里面是用户的权限信息
  15. * object 是url
  16. * configAttributes 所需的权限
  17. * @see org.springframework.security.access.AccessDecisionManager#decide(org.springframework.security.core.Authentication, java.lang.Object, java.util.Collection)
  18. */
  19. @Override
  20. public void decide(Authentication authentication, Object object,
  21. Collection<ConfigAttribute> configAttributes)
  22. throws AccessDeniedException, InsufficientAuthenticationException {
  23. // 对应url没有权限时,直接跳出方法
  24. if(configAttributes == null){
  25. return;
  26. }
  27. Iterator<ConfigAttribute> ite=configAttributes.iterator();
  28. //判断用户所拥有的权限,是否符合对应的Url权限,如果实现了UserDetailsService,则用户权限是loadUserByUsername返回用户所对应的权限
  29. while(ite.hasNext()){
  30. ConfigAttribute ca=ite.next();
  31. String needRole=((SecurityConfig)ca).getAttribute();
  32. for(GrantedAuthority ga : authentication.getAuthorities()){
  33. System.out.println(":::::::::::::"+ga.getAuthority());
  34. if(needRole.equals(ga.getAuthority())){
  35. return;
  36. }
  37. }
  38. }
  39. //注意:执行这里,后台是会抛异常的,但是界面会跳转到所配的access-denied-page页面
  40. throw new AccessDeniedException("no right");
  41. }
  42. @Override
  43. public boolean supports(ConfigAttribute attribute) {
  44. return true;
  45. }
  46. @Override
  47. public boolean supports(Class<?> clazz) {
  48. return true;
  49. }
  50. }
package com.ultrapower.me.util.security.interceptor;

import java.util.Collection;

import java.util.Iterator; import org.springframework.security.access.AccessDecisionManager;

import org.springframework.security.access.AccessDeniedException;

import org.springframework.security.access.ConfigAttribute;

import org.springframework.security.access.SecurityConfig;

import org.springframework.security.authentication.InsufficientAuthenticationException;

import org.springframework.security.core.Authentication;

import org.springframework.security.core.GrantedAuthority; public class SecurityAccessDecisionManager implements AccessDecisionManager {
/**
* 检查用户是否够权限访问资源
* authentication 是从spring的全局缓存SecurityContextHolder中拿到的,里面是用户的权限信息
* object 是url
* configAttributes 所需的权限
* @see org.springframework.security.access.AccessDecisionManager#decide(org.springframework.security.core.Authentication, java.lang.Object, java.util.Collection)
*/
@Override
public void decide(Authentication authentication, Object object,
Collection&lt;ConfigAttribute&gt; configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException {
// 对应url没有权限时,直接跳出方法
if(configAttributes == null){
return;
} Iterator&lt;ConfigAttribute&gt; ite=configAttributes.iterator();
//判断用户所拥有的权限,是否符合对应的Url权限,如果实现了UserDetailsService,则用户权限是loadUserByUsername返回用户所对应的权限
while(ite.hasNext()){
ConfigAttribute ca=ite.next();
String needRole=((SecurityConfig)ca).getAttribute();
for(GrantedAuthority ga : authentication.getAuthorities()){
System.out.println(":::::::::::::"+ga.getAuthority());
if(needRole.equals(ga.getAuthority())){
return;
}
}
}
//注意:执行这里,后台是会抛异常的,但是界面会跳转到所配的access-denied-page页面
throw new AccessDeniedException("no right");
}
@Override
public boolean supports(ConfigAttribute attribute) {
return true;
}
@Override
public boolean supports(Class&lt;?&gt; clazz) {
return true;
}

}

4.实现AuthenticationProvider,自定义参数验证

这种验证以前项目用过,现在没有写示例代码,先写下大概流程和需要用到的类
这种验证的好处:可以在自定义登录界面添加登录时需要的参数,如多个验证码等、可以修改默认登录名称和密码的参数名

整体流程:
1.用户登录时,先经过自定义的passcard_filter过滤器,该过滤器继承了AbstractAuthenticationProcessingFilter,并且绑定了登录失败和成功时需要的处理器(跳转页面使用)
2.执行attemptAuthentication方法,可以通过request获取登录页面传递的参数,实现自己的逻辑,并且把对应参数set到AbstractAuthenticationToken的实现类中
3.验证逻辑走完后,调用 this.getAuthenticationManager().authenticate(token);方法,执行AuthenticationProvider的实现类的supports方法
4.如果返回true则继续执行authenticate方法
5.在authenticate方法中,首先可以根据用户名获取到用户信息,再者可以拿自定义参数和用户信息做逻辑验证,如密码的验证
6.自定义验证通过以后,获取用户权限set到User中,用于springSecurity做权限验证
7.this.getAuthenticationManager().authenticate(token)方法执行完后,会返回Authentication,如果不为空,则说明验证通过
8.验证通过后,可实现自定义逻辑操作,如记录cookie信息
9.attemptAuthentication方法执行完成后,由springSecuriy来进行对应权限验证,成功于否会跳转到相对应处理器设置的界面。

1.自定义PassCardAuthenticationToken类,继承AbstractAuthenticationToken类,用于定义参数,需要实现的方法
  1. /**
  2. * 凭证,用户密码
  3. */
  4. @Override
  5. public Object getCredentials() {
  6. return password;
  7. }
  8. /**
  9. * 当事人,登录名 用户Id
  10. */
  11. @Override
  12. public Object getPrincipal() {
  13. return userID;
  14. }
/**
* 凭证,用户密码
*/
@Override
public Object getCredentials() {
return password;
}
/**
* 当事人,登录名 用户Id
*/
@Override
public Object getPrincipal() {
return userID;
}</pre><br><br></div>
2.User类要实现Authentication,需要实现的方法
  1. /**
  2. * 返回用户所属权限
  3. */
  4. @Override
  5. public Collection<GrantedAuthority> getAuthorities() {
  6. return this.accesses;
  7. }
  8. @Override
  9. public Object getCredentials() {
  10. return null;
  11. }
  12. @Override
  13. public Object getDetails() {
  14. return null;
  15. }
  16. /**
  17. * 登录名称
  18. */
  19. @Override
  20. public Object getPrincipal() {
  21. return loginName;
  22. }
  23. /**
  24. * 是否认证
  25. */
  26. @Override
  27. public boolean isAuthenticated() {
  28. return this.authenticated;
  29. }
  30. /**
  31. * 设置是否认证字段
  32. */
  33. @Override
  34. public void setAuthenticated(boolean isAuthenticated)
  35. throws IllegalArgumentException {
  36. this.authenticated=isAuthenticated;
  37. }
/**
* 返回用户所属权限
*/
@Override
public Collection<GrantedAuthority> getAuthorities() {
return this.accesses;
}
@Override
public Object getCredentials() {
return null;
}
@Override
public Object getDetails() {
return null;
}
/**
* 登录名称
*/
@Override
public Object getPrincipal() {
return loginName;
}
/**
* 是否认证
*/
@Override
public boolean isAuthenticated() {
return this.authenticated;
}
/**
* 设置是否认证字段
*/
@Override
public void setAuthenticated(boolean isAuthenticated)
throws IllegalArgumentException {
this.authenticated=isAuthenticated;
}</pre><br><br></div>
3.需要userService实现AuthenticationProvider的 authenticate(Authentication authentication)方法
  
  1. @SuppressWarnings("unchecked")
  2. @Override
  3. public Authentication authenticate(Authentication authentication)
  4. throws AuthenticationException {
  5. PassCardAuthenticationToken token=(PassCardAuthenticationToken)authentication;
  6. /*
  7. * 这里进行逻辑认证操作,可以获取token中的属性来自定义验证逻辑,代码验证逻辑可以不用管
  8. * 如果使用UserDetailsService的实现类来验证,就只能获取userName,不够灵活
  9. */
  10. if(token.getUserID()!=null&&token.getPassword()!=null){
  11. User user=(User)this.getDao().executeQueryUnique("User.loadByLoginName", QueryCmdType.QUERY_NAME, token.getUserID());
  12. String password=token.getPassword();
  13. if(this.passwordEncoder!=null){
  14. password=this.passwordEncoder.encodePassword(password, null);
  15. }
  16. if(!password.equalsIgnoreCase(user.getPassword())){
  17. token.setErrCode("2");
  18. return null;
  19. }
  20. if( token.isEnablePasscard() && usePassCard ){//token中激活密码卡且系统使用密码卡
  21. int position1=((token.getRow1()-1)*7)+token.getColumn1();
  22. int position2=((token.getRow2()-1)*7)+token.getColumn2();
  23. //System.out.println( "---pos:"+position1+"---"+position2 );
  24. if(user.getPassCardId()==null){
  25. token.setErrCode("10");
  26. return null;
  27. }
  28. PassCard passcard=this.passCardDao.findById(user.getPassCardId(), false);
  29. if(passcard==null||passcard.getStatus()==PassCardHelper.STATUS_CANCEL ){
  30. token.setErrCode("10");
  31. return null;
  32. }
  33. if(passcard.getConfusedContent()==null || passcard.getConfusedContent().length()<7*7*32 ){
  34. token.setErrCode("10");
  35. return null;
  36. }
  37. String content=passcard.getConfusedContent();
  38. int perLen=content.length()/49;
  39. String str1=content.substring((position1-1)*perLen, position1*perLen);
  40. String str2=content.substring((position2-1)*perLen, position2*perLen);
  41. String inputStr1=token.getCard1();
  42. String inputStr2=token.getCard2();
  43. if(this.passwordEncoder!=null){
  44. inputStr1 = md5.getMD5ofStr(md5.getMD5ofStr(inputStr1));
  45. inputStr2 = md5.getMD5ofStr(md5.getMD5ofStr(inputStr2));
  46. }
  47. if((!str1.equalsIgnoreCase(inputStr1))||(!str2.equalsIgnoreCase(inputStr2))){
  48. token.setErrCode("10");
  49. return null;
  50. }
  51. }
  52. user.setLastIp(token.getIp());
  53. user.setLastLogin(new Date());
  54. this.getDao().saveOrUpdate(user);
  55. user.setAuthenticated(true);
  56. /*
  57. * 导入一次角色权限,并且把权限set到User中,用于spring验证用户权限(getAuthorities方法)
  58. */
  59. List<UserRole> userRoles=(List<UserRole>)this.getDao().executeQueryList("UserRole.listRoleByUserID", QueryCmdType.QUERY_NAME, -1, -1, user.getId());
  60. Set<GrantedAuthority> accesses=new HashSet<GrantedAuthority>();
  61. for(UserRole ur:userRoles){
  62. accesses.add(ur.getRole());
  63. }
  64. user.getOrg().getOrgName();
  65. if(user.getOrg().getCertTypes()!=null) user.getOrg().getCertTypes().size();//延迟载入一下
  66. user.setAccesses(accesses);
  67. return user;
  68. }
  69. return null;
  70. }
@SuppressWarnings("unchecked")
@Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
PassCardAuthenticationToken token=(PassCardAuthenticationToken)authentication;
/*
* 这里进行逻辑认证操作,可以获取token中的属性来自定义验证逻辑,代码验证逻辑可以不用管
* 如果使用UserDetailsService的实现类来验证,就只能获取userName,不够灵活
*/
if(token.getUserID()!=null&&token.getPassword()!=null){
User user=(User)this.getDao().executeQueryUnique("User.loadByLoginName", QueryCmdType.QUERY_NAME, token.getUserID());
		String password=token.getPassword();
if(this.passwordEncoder!=null){
password=this.passwordEncoder.encodePassword(password, null);
} if(!password.equalsIgnoreCase(user.getPassword())){ token.setErrCode("2");
return null;
} if( token.isEnablePasscard() &amp;&amp; usePassCard ){//token中激活密码卡且系统使用密码卡 int position1=((token.getRow1()-1)*7)+token.getColumn1();
int position2=((token.getRow2()-1)*7)+token.getColumn2();
//System.out.println( "---pos:"+position1+"---"+position2 ); if(user.getPassCardId()==null){
token.setErrCode("10");
return null;
}
PassCard passcard=this.passCardDao.findById(user.getPassCardId(), false); if(passcard==null||passcard.getStatus()==PassCardHelper.STATUS_CANCEL ){
token.setErrCode("10");
return null;
}
if(passcard.getConfusedContent()==null || passcard.getConfusedContent().length()&lt;7*7*32 ){
token.setErrCode("10");
return null;
} String content=passcard.getConfusedContent();
int perLen=content.length()/49;
String str1=content.substring((position1-1)*perLen, position1*perLen);
String str2=content.substring((position2-1)*perLen, position2*perLen);
String inputStr1=token.getCard1();
String inputStr2=token.getCard2();
if(this.passwordEncoder!=null){
inputStr1 = md5.getMD5ofStr(md5.getMD5ofStr(inputStr1));
inputStr2 = md5.getMD5ofStr(md5.getMD5ofStr(inputStr2));
} if((!str1.equalsIgnoreCase(inputStr1))||(!str2.equalsIgnoreCase(inputStr2))){
token.setErrCode("10");
return null;
}
}
user.setLastIp(token.getIp());
user.setLastLogin(new Date());
this.getDao().saveOrUpdate(user);
user.setAuthenticated(true);
/*
* 导入一次角色权限,并且把权限set到User中,用于spring验证用户权限(getAuthorities方法)
*/
List&lt;UserRole&gt; userRoles=(List&lt;UserRole&gt;)this.getDao().executeQueryList("UserRole.listRoleByUserID", QueryCmdType.QUERY_NAME, -1, -1, user.getId());
Set&lt;GrantedAuthority&gt; accesses=new HashSet&lt;GrantedAuthority&gt;();
for(UserRole ur:userRoles){
accesses.add(ur.getRole());
}
user.getOrg().getOrgName();
if(user.getOrg().getCertTypes()!=null) user.getOrg().getCertTypes().size();//延迟载入一下
user.setAccesses(accesses);
return user;
}
return null;
}</pre><br></div>
   重写supports(Class<? extends Object> authentication)方法,authentication要
  1. /**
  2. * 如果此处验证不通过,是不会执行authentication方法的
  3. */
  4. @Override
  5. public boolean supports(Class<? extends Object> authentication) {
  6. return authentication.equals(PassCardAuthenticationToken.class);
  7. }
/**
* 如果此处验证不通过,是不会执行authentication方法的
*/
@Override
public boolean supports(Class<? extends Object> authentication) {
return authentication.equals(PassCardAuthenticationToken.class);
}

4.定义filter,实现AbstractAuthenticationProcessingFilter的attemptAuthentication方法,用于获取在登录页面传递过来的参数,spring默认只获取userName(j_username),password(j_username),而且实现UserDetailsService时只传递username


  1. import java.io.IOException;
  2. import java.util.Date;
  3. import javax.servlet.ServletException;
  4. import javax.servlet.http.Cookie;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import javax.servlet.http.HttpSession;
  8. import org.apache.log4j.Logger;
  9. import org.springframework.security.core.Authentication;
  10. import org.springframework.security.core.AuthenticationException;
  11. import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
  12. import org.springframework.util.StringUtils;
  13. import cn.edu.jszg.cert.user.UserLog;
  14. import cn.edu.jszg.cert.user.UserLogService;
  15. import cn.edu.jszg.cert.web.WebApplicationConfiguration;
  16. import cn.edu.jszg.cert.web.controller.portal.auth.RemoteDataValidator;
  17. import com.google.code.kaptcha.servlet.KaptchaServlet;
  18. public class PasscardAuthenticationProcessingFilter extends
  19. AbstractAuthenticationProcessingFilter {
  20. private String successPage = "/home/admin/index";
  21. private String failurePage = "/public/adminLoginEntry";
  22. private boolean forward = false;
  23. private boolean useVerifyCode=true;
  24. private String certLoginUrl;
  25. static Logger logger = Logger.getLogger(PasscardAuthenticationProcessingFilter.class);
  26. private WebApplicationConfiguration config;
  27. private UserLogService userLogService;
  28. public void setConfig(WebApplicationConfiguration config) {
  29. this.config = config;
  30. }
  31. /**
  32. * 实现AbstractAuthenticationProcessingFilter的有参构造
  33. * 没记错的话,相当于该filter的访问路径
  34. */
  35. protected PasscardAuthenticationProcessingFilter() {
  36. super("/adminLoginCheck");
  37. }
  38. public void setUseVerifyCode(boolean useVerifyCode) {
  39. this.useVerifyCode = useVerifyCode;
  40. }
  41. public void setUserLogService(UserLogService userLogService) {
  42. this.userLogService = userLogService;
  43. }
  44. public boolean validate(HttpServletRequest request) {
  45. String userId = request.getParameter("username");
  46. String md2 = request.getParameter("m");
  47. String l = request.getParameter("l");
  48. if (userId == null || md2 == null || l == null) {
  49. return false;
  50. }
  51. long longTime = Long.parseLong(l);
  52. if (longTime < new Date().getTime()) {
  53. return false;
  54. }
  55. try {
  56. String md1 = RemoteDataValidator.genExamMd5Digest(userId, longTime);
  57. if (md1.equals(md2))
  58. return true;
  59. } catch (Exception e) {
  60. //e.printStackTrace();
  61. }
  62. return false;
  63. }
  64. /**
  65. * 可以通过request获取页面传递过来的参数,并且set到相应的token中
  66. */
  67. @Override
  68. public Authentication attemptAuthentication(HttpServletRequest request,
  69. HttpServletResponse response) throws AuthenticationException,
  70. IOException, ServletException {
  71. //      logger.warn("-----------------start证书登录用户----------");
  72. HttpSession s = request.getSession(true);
  73. PassCardAuthenticationToken token = new PassCardAuthenticationToken();
  74. String verifyCode = request.getParameter("verifyCode");
  75. String userID = request.getParameter("username");
  76. //....此处省略获取参数,并且验证、赋值的逻辑
  77. Authentication auth = null;
  78. try {
  79. //此处调用getAuthenticationManager的authenticate方法,当supports方法返回true时执行authenticate方法
  80. auth = this.getAuthenticationManager().authenticate(token);
  81. //此处为登录成功后,相应的处理逻辑
  82. if (auth == null || !auth.isAuthenticated()) {
  83. s.setAttribute("__login_error", token.getErrCode());
  84. } else  {
  85. s.removeAttribute("__login_error");
  86. s.removeAttribute("__login_username");
  87. s.removeAttribute("__cert_userid");
  88. if( token.isEnablePasscard()) {
  89. s.removeAttribute("__passcard_row1");
  90. s.removeAttribute("__passcard_row2");
  91. s.removeAttribute("__passcard_column1");
  92. s.removeAttribute("__passcard_column2");
  93. }
  94. }
  95. } catch (AuthenticationException e) {
  96. s.setAttribute("__login_error", token.getErrCode());
  97. throw e;
  98. }
  99. return auth;
  100. }
  101. public void setSuccessPage(String successPage) {
  102. this.successPage = successPage;
  103. }
  104. public void setFailurePage(String failurePage) {
  105. this.failurePage = failurePage;
  106. }
  107. public void setForward(boolean forward) {
  108. this.forward = forward;
  109. }
  110. public void setCertLoginUrl(String certLoginUrl) {
  111. this.certLoginUrl = certLoginUrl;
  112. }
  113. @Override
  114. public void afterPropertiesSet() {
  115. super.afterPropertiesSet();
  116. /*
  117. *该处理器实现了AuthenticationSuccessHandler, AuthenticationFailureHandler
  118. *用于处理登录成功或者失败后,跳转的界面
  119. */
  120. AuthenticationResultHandler handler = new AuthenticationResultHandler();
  121. handler.setForward(forward);
  122. handler.setLoginFailurePage(failurePage);
  123. handler.setLoginSuccessPage(successPage);
  124. handler.setCertLoginUrl(certLoginUrl);
  125. //设置父类中的处理器
  126. this.setAuthenticationSuccessHandler(handler);
  127. this.setAuthenticationFailureHandler(handler);
  128. }
  129. }
import java.io.IOException;
import java.util.Date; import javax.servlet.ServletException;

import javax.servlet.http.Cookie;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession; import org.apache.log4j.Logger;

import org.springframework.security.core.Authentication;

import org.springframework.security.core.AuthenticationException;

import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;

import org.springframework.util.StringUtils; import cn.edu.jszg.cert.user.UserLog;

import cn.edu.jszg.cert.user.UserLogService;

import cn.edu.jszg.cert.web.WebApplicationConfiguration;

import cn.edu.jszg.cert.web.controller.portal.auth.RemoteDataValidator; import com.google.code.kaptcha.servlet.KaptchaServlet; public class PasscardAuthenticationProcessingFilter extends

AbstractAuthenticationProcessingFilter {

private String successPage = "/home/admin/index";

private String failurePage = "/public/adminLoginEntry";

private boolean forward = false;

private boolean useVerifyCode=true;

private String certLoginUrl;
static Logger logger = Logger.getLogger(PasscardAuthenticationProcessingFilter.class);

private WebApplicationConfiguration config;
private UserLogService userLogService; public void setConfig(WebApplicationConfiguration config) {
this.config = config;
} /**
* 实现AbstractAuthenticationProcessingFilter的有参构造
* 没记错的话,相当于该filter的访问路径
*/
protected PasscardAuthenticationProcessingFilter() {
super("/adminLoginCheck");
} public void setUseVerifyCode(boolean useVerifyCode) {
this.useVerifyCode = useVerifyCode;
} public void setUserLogService(UserLogService userLogService) {
this.userLogService = userLogService;
} public boolean validate(HttpServletRequest request) {
String userId = request.getParameter("username");
String md2 = request.getParameter("m");
String l = request.getParameter("l");
if (userId == null || md2 == null || l == null) {
return false;
}
long longTime = Long.parseLong(l);
if (longTime &lt; new Date().getTime()) {
return false;
} try {
String md1 = RemoteDataValidator.genExamMd5Digest(userId, longTime);
if (md1.equals(md2))
return true; } catch (Exception e) {
//e.printStackTrace();
} return false;
} /**
* 可以通过request获取页面传递过来的参数,并且set到相应的token中
*/
@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException,
IOException, ServletException {

// logger.warn("-----------------start证书登录用户----------");

HttpSession s = request.getSession(true);

PassCardAuthenticationToken token = new PassCardAuthenticationToken();

	String verifyCode = request.getParameter("verifyCode");
String userID = request.getParameter("username");
//....此处省略获取参数,并且验证、赋值的逻辑
Authentication auth = null; try {
//此处调用getAuthenticationManager的authenticate方法,当supports方法返回true时执行authenticate方法
auth = this.getAuthenticationManager().authenticate(token); //此处为登录成功后,相应的处理逻辑
if (auth == null || !auth.isAuthenticated()) {
s.setAttribute("__login_error", token.getErrCode());
} else {
s.removeAttribute("__login_error");
s.removeAttribute("__login_username");
s.removeAttribute("__cert_userid");
if( token.isEnablePasscard()) {
s.removeAttribute("__passcard_row1");
s.removeAttribute("__passcard_row2");
s.removeAttribute("__passcard_column1");
s.removeAttribute("__passcard_column2");
}
}
} catch (AuthenticationException e) {
s.setAttribute("__login_error", token.getErrCode());
throw e;
} return auth;
} public void setSuccessPage(String successPage) {
this.successPage = successPage;
} public void setFailurePage(String failurePage) {
this.failurePage = failurePage;
} public void setForward(boolean forward) {
this.forward = forward;
} public void setCertLoginUrl(String certLoginUrl) {
this.certLoginUrl = certLoginUrl;
} @Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
/*
*该处理器实现了AuthenticationSuccessHandler, AuthenticationFailureHandler
*用于处理登录成功或者失败后,跳转的界面
*/
AuthenticationResultHandler handler = new AuthenticationResultHandler();
handler.setForward(forward);
handler.setLoginFailurePage(failurePage);
handler.setLoginSuccessPage(successPage);
handler.setCertLoginUrl(certLoginUrl);
//设置父类中的处理器
this.setAuthenticationSuccessHandler(handler);
this.setAuthenticationFailureHandler(handler); }

}

最后为spring-security配置文件中的配置,需要添加authentication-provider的引用,和filter的配置

  1. <security:authentication-manager alias="authenticationManager">
  2. <!-- 注意,这里仅仅是系统默认的认证机制,请在正式系统中明确知道其功能再使用 -->
  3. <security:authentication-provider ref="acocunt_defaultAnthentiactionProvider"/>
  4. <security:authentication-provider ref="registrationService"/>
  5. <security:authentication-provider ref="enrollmentService"/>
  6. <security:authentication-provider ref="userService"/>
  7. </security:authentication-manager>
  8. <bean id="passcard_filter" class="cn.edu.jszg.cert.security.PasscardAuthenticationProcessingFilter">
  9. <property name="authenticationManager" ref="authenticationManager"/>
  10. <property name="useVerifyCode" value="true"/>
  11. <property name="failurePage" value="/portal/home/auth/"></property>
  12. <property name="config" ref="webAppConfig"/>
  13. <property name="userLogService" ref="userLogService" />
  14. <property name="certLoginUrl" value="${cert.login.url}"/>
  15. </bean>
<security:authentication-manager alias="authenticationManager">
<!-- 注意,这里仅仅是系统默认的认证机制,请在正式系统中明确知道其功能再使用 -->
<security:authentication-provider ref="acocunt_defaultAnthentiactionProvider"/>
<security:authentication-provider ref="registrationService"/>
<security:authentication-provider ref="enrollmentService"/>
<security:authentication-provider ref="userService"/>
</security:authentication-manager>
<bean id="passcard_filter" class="cn.edu.jszg.cert.security.PasscardAuthenticationProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="useVerifyCode" value="true"/>
<property name="failurePage" value="/portal/home/auth/"></property>
<property name="config" ref="webAppConfig"/>
<property name="userLogService" ref="userLogService" />
<property name="certLoginUrl" value="${cert.login.url}"/>
</bean>

还要在http中添加<security:custom-filter ref="passcard_filter" after="SECURITY_CONTEXT_FILTER"/>


  •                 </ul>
    <div style="clear:both; height:10px;"></div>
    </div>
posted @
2018-03-08 16:09 
星朝 
阅读(...) 
评论(...) 
编辑 
收藏

spring security四种实现方式的更多相关文章

  1. 【Spring】12、Spring Security 四种使用方式

    spring security使用分类: 如何使用spring security,相信百度过的都知道,总共有四种用法,从简到深为:1.不用数据库,全部数据写在配置文件,这个也是官方文档里面的demo: ...

  2. Spring AOP四种实现方式Demo详解与相关知识探究

    一.前言 在网络上看到一篇博客Spring实现AOP的4种方式,博主写的很通俗易懂,但排版实在抓狂,对于我这么一个对排版.代码格式有强迫症的人来说,实在是不能忍受~~~~(>_<)~~~~ ...

  3. 读书笔记——spring cloud 中 HystrixCommand的四种执行方式简述

    读了<Spring Cloud 微服务实战>第151-154页, 总结如下: Hystrix存在两种Command,一种是HystrixCommand,另一种是HystrixObserva ...

  4. 【spring springmvc】这里有你想要的SpringMVC的REST风格的四种请求方式

    概述 之前的文章springmvc使用注解声明控制器与请求映射有简单提到过控制器与请求映射,这一次就详细讲解一下SpringMVC的REST风格的四种请求方式及其使用方法. 你能get的知识点 1.什 ...

  5. Android开发之基本控件和详解四种布局方式

    Android中的控件的使用方式和iOS中控件的使用方式基本相同,都是事件驱动.给控件添加事件也有接口回调和委托代理的方式.今天这篇博客就总结一下Android中常用的基本控件以及布局方式.说到布局方 ...

  6. spring ioc三种注入方式

    spring ioc三种注入方式 IOC ,全称 (Inverse Of Control) ,中文意思为:控制反转 什么是控制反转? 控制反转是一种将组件依赖关系的创建和管理置于程序外部的技术. 由容 ...

  7. lua中for循环的四种遍历方式

    lua中for的四种遍历方式区别 table.maxn 取最大的整数key #table 从1开始的顺序整数最大值,如1,2,3,6 #table == 3   key,value pairs 取每一 ...

  8. Android数据的四种存储方式SharedPreferences、SQLite、Content Provider和File (一) —— 总览

    Android数据的四种存储方式SharedPreferences.SQLite.Content Provider和File (一) —— 总览   作为一个完成的应用程序,数据存储操作是必不可少的. ...

  9. HttpwebClient的四种请求方式

    最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷.      本文旨在发布代码,供自己参考,也供大家参考,谢谢. 正题: Ht ...

随机推荐

  1. IT外包概要

    IT外包 前两天和朋友聊起这个外包的问题,就顺便给他说了一下,自己也整理了一下,发出来,方便更多的人. 如果有说的不准确的地方欢迎大家补充分享. 大致分两种: 项目外包, 人力外包. 简而言之:项目外 ...

  2. Java虚拟机原理图解-- 1.1、class文件基本组织结构 [转]

    作为Java程序猿,我们知道,我们写好的.java 源代码,最后会被Java编译器编译成后缀为.class的文件,该类型的文件是由字节组成的文件,又叫字节码文件.那么,class字节码文件里面到底是有 ...

  3. 2019-6-23-win10-uwp-未给任务-GenerateAppxPackageRecipe-的必需参数-AppxManifestXml-赋值

    title author date CreateTime categories win10 uwp 未给任务 GenerateAppxPackageRecipe 的必需参数 AppxManifestX ...

  4. Linux时间设置命令

    1.date: 语法格式:date [-u] [-d datestr] [-s datestr] [--utc] [--universal] [--date=datestr] [--set=dates ...

  5. spring入门案例分析及原理

    Springmvc执行原理: 一. 入门案例的执行流程 1. 当启动Tomcat服务器的时候,因为配置了load-on-startup标签,所以会创建DispatcherServlet对象,就会加载s ...

  6. 跟我一起做一个vue的小项目(十)

    接下来我们对城市列表页面进行优化,除了对数据优化,也会进行节流处理 //src\pages\city\components\Alphabet.vue <template> <ul c ...

  7. 微信小程序之组件的集合(三)

    看看音乐播放组件是如何实现完成的音乐的播放的!!! 一.音乐music组件的开发 1.页面以及页面样式的开发 // music组件页面开发 <view hidden="{{hidden ...

  8. tyvj 1423 GF和猫咪的玩具

    传送门 解题思路 题目比较水,floyd求出最短路取个最小值即可.结果joyoi时限写错了..好像只有0ms才能过??突然发现加了快读就T不加就A,数据在10000以下的还是scanf快啊. 代码 # ...

  9. TZ_11_Spring-Boot的整合SpringMvc和MyBatis

    1.整合SpringMVC 虽然默认配置已经可以使用SpringMVC了,不过我们有时候需要进行自定义配置. 1>修改方式 通过application.yaml 此名字不需要使用@Propert ...

  10. android 复制到剪切板

    The Clipboard Framework 当使用clipboard framework时,把数据放在一个剪切对象(clip object)里,然后这个对象会放在系统的剪贴板里. clip obj ...