做权限管理的时候学习了security的使用,包括官方的使用配置示例,学习新东西的时候最好参照官方的使用文档,英文的也好,纵使英文不好,慢慢阅读,养成好习惯,自己的英文水平也会慢慢提高,搞开发英文水平也是很重要的。
首先引入security所需的包,工程使用maven构建,控制某个用户是否有对资源的访问权限
<!--security-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-cas</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
在web.xml中配置过滤器,引入security的配置文件,配置过滤器时注意名字springSecurityFilterChain
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/spring/applicationContext.xml,classpath:/spring/application-security.xml</param-value>
</context-param>
<!-- 权限 -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在applicationContext-security.xml使用命名空间配置
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<intercept-url pattern="/login.jsp" filters="none"/>//默认login.jsp不拦截
<form-login login-page="/login.jsp" authentication-failure-url="/403.jsp" default-target-url="/index.jsp"/>//自定义登录界面
<http-basic/>
<logout logout-success-url="/login.jsp"/>
<http pattern="/js/**" security="none"/>
<http pattern="/css/**" security="none"></http>
<http pattern="/login.jsp" security="none"/>
<http use-expressions="true" entry-point-ref="authenticationProcessingFilterEntryPoint">
<logout/>
<remember-me />
<session-management invalid-session-url="/timeout.jsp">
<concurrency-control max-sessions="30" error-if-maximum-exceeded="true" />
</session-management>
<custom-filter ref="loginFilter" position="FORM_LOGIN_FILTER" />
<custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR"/><!-- 自定义filter在默认过滤器之前 -->
</http>
<beans:bean id="loginFilter"
class="com.amplesky.security.MyUsernamePasswordAuthenticationFilter">
<!-- 处理登录 -->
<beans:property name="filterProcessesUrl" value="/j_spring_security_check"></beans:property>
<beans:property name="authenticationSuccessHandler" ref="loginLogAuthenticationSuccessHandler"></beans:property>
<beans:property name="authenticationFailureHandler" ref="simpleUrlAuthenticationFailureHandler"></beans:property>
<beans:property name="authenticationManager" ref="myAuthenticationManager"></beans:property>
</beans:bean>
<beans:bean id="loginLogAuthenticationSuccessHandler"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<beans:property name="defaultTargetUrl" value="/index.jsp"></beans:property>
</beans:bean>
<beans:bean id="simpleUrlAuthenticationFailureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<beans:property name="defaultFailureUrl" value="/login.jsp"></beans:property>
</beans:bean>
<!-- 用户自定义filter必须包含三个属性 -->
<beans:bean id="myFilter" class="com.amplesky.security.MySecurityFilter">
<!-- 用户拥有的权限 -->
<beans:property name="authenticationManager" ref="myAuthenticationManager"/>
<!-- 用户是否用户访问资源的权限-->
<beans:property name="accessDecisionManager" ref="myAccessDecisionManager"/>
<!-- 资源与权限的关系-->
<beans:property name="securityMedataSource" ref="mySecurityMetadataSource"/>
</beans:bean>
<!-- 认证管理器,实现UsersDetailsService接口 -->
<authentication-manager alias="myAuthenticationManager">
<authentication-provider user-service-ref="myUserDetailServiceImpl"/>
</authentication-manager>
<!-- 访问决策层,决定某个用户具有的角色,是否有足够角色访问某个资源 -->
<beans:bean id="myAccessDecisionManager" class="com.amplesky.security.MyAccessDecisionManager">
</beans:bean>
<!-- 资源数据定义,定义某一资源能被那些角色访问 -->
<beans:bean id="mySecurityMetadataSource" class="com.amplesky.security.MySecurityMetadataSource" init-method="loadResourceDefine">
</beans:bean>
<!-- service -->
<beans:bean id="myUserDetailServiceImpl" class="com.amplesky.security.MyUserDetailServiceImpl">
</beans:bean>
<!-- 未登录的切入点 -->
<beans:bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/login.jsp"></beans:property>
</beans:bean>
</beans:beans>
定义三个对象,五张表
User.java Role.java Resource.java
T_User表
用于存放用户信息,此处只存放基础信息
T_Role表
用于存放系统角色信息
T_User_Role表
用于存放系统用户与角色的匹配关系
T_Resource表
用于存放资源表
T_Role_Resource表
存放角色对应的资源表
登录页面form提交的路径
<form action="j_spring_security_check" method="post">
登录处理的filter
public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter{
public static final String VALIDATE_CODE = "validateCode";
public static final String USERNAME = "username";
public static final String PASSWORD = "password";
@Resource
private LoginDao loginDao;
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (!request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
String username = request.getParameter("username");
String password = request.getParameter("password");
//验证用户账号与密码是否对应
username = username.trim();
Users users = this.loginDao.findByName(username);
if(users == null || !users.getPassword().equals(password)) {
/*
if (forwardToDestination) {
request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);
} else {
HttpSession session = request.getSession(false);
if (session != null || allowSessionCreation) {
request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);
}
}
*/
throw new AuthenticationServiceException("password or username is notEquals");
}
//UsernamePasswordAuthenticationToken实现 Authentication
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
// Place the last username attempted into HttpSession for views
// 允许子类设置详细属性
setDetails(request, authRequest);
// 运行UserDetailsService的loadUserByUsername 再次封装Authentication
return this.getAuthenticationManager().authenticate(authRequest);
}
}
MyUserDetailServiceIMpl.java
public class MyUserDetailServiceImpl implements UserDetailsService{
@Resource
private LoginDao loginDao;
@Override
public UserDetails loadUserByUsername(String usersname) {
// TODO Auto-generated method stub
System.out.println("Usersname is:"+usersname);
Users Users=this.loginDao.findByName(usersname);
Collection<GrantedAuthority> grantedAuths=obtionGrantedAuthorities(this.loginDao.findByName(usersname));
boolean enables = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
User Usersdetail=new User(Users.getLoginId(),Users.getPassword(),enables, accountNonExpired, credentialsNonExpired, accountNonLocked, grantedAuths);
return Usersdetail;
}
//取得用户权限
public Set<GrantedAuthority> obtionGrantedAuthorities(Users user){
Set<GrantedAuthority> authSet = new HashSet<GrantedAuthority>();
Set<Role> roles = loginDao.findRoleByUsers(user); //根据用户取得用户的角色
for(Role role : roles) {
authSet.add(new GrantedAuthorityImpl(role.getRoleName()));
}
return authSet;
}
}
MySecurityMetadaSource.java //加载所有的资源和权限关系
public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource{
@Resource(name="resourceDao")
private ResourceDao resourceDao;
public void setResourceDao(ResourceDao resourceDao){
this.resourceDao=resourceDao;
}
private static Map<String,Collection<ConfigAttribute>> resourceMap=null;
//加载所有的资源和权限关系
public void loadResourceDefine(){
if(resourceMap==null){
resourceMap=new HashMap<String,Collection<ConfigAttribute>>();
List<Resource> list=resourceDao.getResourceAll();
for(Resource functionTree:list){
Collection<ConfigAttribute> configAttributes=new ArrayList<ConfigAttribute>();
List<Role> roles=resourceDao.getRoleByFunc(functionTree);//根据资源得到需要的角色
for(Role role:roles){
ConfigAttribute configAttribute=new SecurityConfig(role.getRoleName());
configAttributes.add(configAttribute);
}
resourceMap.put(functionTree.getUrl(), configAttributes);
}
}
Set<Map.Entry<String, Collection<ConfigAttribute>>> resourceSet = resourceMap.entrySet();
Iterator<Map.Entry<String, Collection<ConfigAttribute>>> iterator = resourceSet.iterator();
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
// TODO Auto-generated method stub
return null;
}
//返回请求资源所需的权限
@Override
public Collection<ConfigAttribute> getAttributes(Object object)
throws IllegalArgumentException {
// TODO Auto-generated method stub
String requestUrl=((FilterInvocation)object).getRequestUrl();
System.out.println("request url is"+requestUrl);
if(resourceMap==null){
loadResourceDefine();
}
return resourceMap.get(requestUrl);
}
@Override
public boolean supports(Class<?> arg0) {
// TODO Auto-generated method stub
return true;
}
public static Map<String,Collection<ConfigAttribute>> getResourceMap() {
return resourceMap;
}
public static void setResourceMap(Map<String,Collection<ConfigAttribute>> resourceMap) {
MySecurityMetadataSource.resourceMap = resourceMap;
}
}
MyAccessDecisionManager.java //访问决策层,决定某个用户具有的角色,是否有足够角色访问某个资源
public class MyAccessDecisionManager implements AccessDecisionManager{
@Override
public void decide(Authentication authentication, Object object,
Collection<ConfigAttribute> configAttribute) throws AccessDeniedException,
InsufficientAuthenticationException {
// TODO Auto-generated method stub
if(configAttribute==null){
return;
}
Iterator<ConfigAttribute> iterator=configAttribute.iterator();
while(iterator.hasNext()){
ConfigAttribute configAttr=iterator.next();
String needPermission=configAttr.getAttribute();
System.out.println(needPermission+">>>>>>");
for(GrantedAuthority ga:authentication.getAuthorities()){
if(needPermission.equals(ga.getAuthority())){//判断需要的角色名是否和用户的角色名相同,否则没有权限
return;
}
}
}
throw new AccessDeniedException(" 没有权限访问! ");
}
@Override
public boolean supports(ConfigAttribute arg0) {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean supports(Class<?> arg0) {
// TODO Auto-generated method stub
return true;
}
}
MySecurityFilter.java //用户自定义filter
public class MySecurityFilter extends AbstractSecurityInterceptor implements Filter{
private FilterInvocationSecurityMetadataSource securityMedataSource;
public void setSecurityMedataSource(
FilterInvocationSecurityMetadataSource securityMedataSource) {
this.securityMedataSource = securityMedataSource;
}
@Override
public Class<? extends Object> getSecureObjectClass() {
// TODO Auto-generated method stub
return FilterInvocation.class;
}
@Override
public SecurityMetadataSource obtainSecurityMetadataSource() {
// TODO Auto-generated method stub
return this.securityMedataSource;
}
private void invoke(FilterInvocation fi){
InterceptorStatusToken token=super.beforeInvocation(fi);
try{
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
}catch(Exception e){
e.printStackTrace();
}finally{
super.afterInvocation(token, null);
}
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@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);
invoke(fi);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}
至此,简单的权限控制完成了,判断用户是否对某个资源具有访问权限,否则提示没有权限访问。