"org.springframework.security:spring-security-web:4.1.0.RELEASE",
"org.springframework.security:spring-security-taglibs:4.1.0.RELEASE",
"org.springframework.security:spring-security-config:4.1.0.RELEASE"
配置framework-spring-security.xml
在framework-spring-mvc.xml引用其它依赖的配置文件
<!--数据库 xml -->
<import resource="dbcp-spring-framework.xml"></import>
<!--spring-security xml -->
<import resource="framework-spring-security.xml"></import>
<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd"> <context:component-scan base-package="com.framework.security"/> <!--<http pattern="/pm/**" security="none" />--> <http pattern="/login.jsp" security="none" /> <http pattern="/common/**" security="none" /> <http pattern="/*.ico" security="none" /> <http use-expressions="false" > <!-- IS_AUTHENTICATED_ANONYMOUSLY 匿名登录 --> <intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" /> <intercept-url pattern="/pm/**/*.jsp" access="ROLE_STATIC" /> <form-login login-page="/login" authentication-failure-url="/login?error=1" authentication-success-forward-url="/main.to" /> <logout invalidate-session="true" logout-url="/logout" logout-success-url="/" /> <http-basic/> <headers > <frame-options disabled="true"></frame-options> </headers> <csrf token-repository-ref="csrfTokenRepository" /> <session-management session-authentication-error-url="/frame.expired" > <!-- max-sessions只容许一个账号登录,error-if-maximum-exceeded 后面账号登录后踢出前一个账号,expired-url session过期跳转界面 --> <concurrency-control max-sessions="1" error-if-maximum-exceeded="false" expired-url="/frame.expired" session-registry-ref="sessionRegistry" /> </session-management> <expression-handler ref="webexpressionHandler" ></expression-handler> </http> <beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" /> <beans:bean id="userDetailsService" class="com.framework.security.UserDetailsServiceImpl" /> <!--配置web端使用权限控制--> <beans:bean id="webexpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler" /> <authentication-manager > <authentication-provider ref="authenticationProvider" /> </authentication-manager> <!-- 自定义userDetailsService, 盐值加密 --> <beans:bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"> <beans:property name="hideUserNotFoundExceptions" value="true" /> <beans:property name="userDetailsService" ref="userDetailsService" /> <beans:property name="passwordEncoder" ref="passwordEncoder" /> <beans:property name="saltSource" ref="saltSource" /> </beans:bean> <!-- Md5加密 --> <beans:bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" /> <!-- 盐值加密 salt对应数据库字段--> <beans:bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource"> <beans:property name="userPropertyToUse" value="salt"/> </beans:bean> <beans:bean id="csrfTokenRepository" class="org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository" /> </beans:beans>
package com.framework.security; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.dao.DataAccessException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.SpringSecurityMessageSource; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.provisioning.JdbcUserDetailsManager; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.*; /**** * @author tzz * @功能描述 * @date 2016/5/3 * 修改人 修改时间 修改说明 ****/ @Service @Transactional(rollbackFor=Exception.class) public class UserDetailsServiceImpl implements UserDetailsService { @Resource CustomUserDao customUserDao; JdbcUserDetailsManager k; private Map<String, UserInfo> userMap = null; protected final Log logger = LogFactory.getLog(getClass()); protected final MessageSourceAccessor messages = SpringSecurityMessageSource .getAccessor(); private String usersByUsernameQuery = "SELECT account,pwd,stat,salt,id,company_id,name,login_stat,login_date ,login_ip FROM USER_ACCOUNT WHERE ACCOUNT = ?"; private String authoritiesByUsernameQuery ="SELECT NAME,POWER_CODE FROM VW_USER_POWER WHERE ACCOUNT_ID = ?"; public UserDetailsServiceImpl() { userMap = new HashMap<>(); } public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { /*SecurityContextHolder.getContext() .getAuthentication().getName();*/ List<UserDetails> users = loadUsersByUsername(username); if (users.size() == 0) { logger.debug("Query returned no results for user '" + username + "'"); throw new UsernameNotFoundException(messages.getMessage( "JdbcDaoImpl.notFound", new Object[] { username }, "Username {0} not found")); } UserInfo user = (UserInfo)users.get(0); Set<GrantedAuthority> dbAuthsSet = new HashSet<>(); dbAuthsSet.addAll(loadUserAuthorities(user.getId())); dbAuthsSet.add(new SimpleGrantedAuthority("ROLE_STATIC")); List<GrantedAuthority> dbAuths = new ArrayList<>(dbAuthsSet); if (dbAuths.size() == 0) { logger.debug("User '" + username + "' has no authorities and will be treated as 'not found'"); throw new UsernameNotFoundException(messages.getMessage( "JdbcDaoImpl.noAuthority", new Object[] { username }, "User {0} has no GrantedAuthority")); } return createUserDetails(username,user,dbAuths); //return user; } protected UserDetails createUserDetails(String username, UserInfo userFromUserQuery, List<GrantedAuthority> combinedAuthorities) { String returnUsername = userFromUserQuery.getUsername(); UserInfo user = new UserInfo(returnUsername,userFromUserQuery.getPassword(), userFromUserQuery.isEnabled(), true, true, true, combinedAuthorities); user.setId(userFromUserQuery.getId()); user.setCompanyId(userFromUserQuery.getCompanyId()); user.setName(userFromUserQuery.getName()); user.setLoginStat(userFromUserQuery.getLoginStat()); user.setLoginDate(userFromUserQuery.getLoginDate()); user.setLoginIP(userFromUserQuery.getLoginIP()); user.setSalt(userFromUserQuery.getSalt()); return user; } /** * Loads authorities by executing the SQL from * <tt>groupAuthoritiesByUsernameQuery</tt>. * * @return a list of GrantedAuthority objects for the user */ protected List<GrantedAuthority> loadUserAuthorities(int userId) { try { return customUserDao.queryForList(this.authoritiesByUsernameQuery, new Object[] { userId },(rs,rowNum)-> { String roleName = getRolePrefix() + rs.getString(2); return new SimpleGrantedAuthority(roleName); }); } catch (Exception e) { e.printStackTrace(); } return null; } public String getRolePrefix() { return "ROLE_"; } /** * Loads authorities by executing the SQL from <tt>authoritiesByUsernameQuery</tt>. * * @return a list of GrantedAuthority objects for the user */ protected List<UserDetails> loadUsersByUsername(String username) { try { return customUserDao.queryForList(this.usersByUsernameQuery, new Object[] { username}, (rs, rowNum) -> { String username1 = rs.getString(1); String password = rs.getString(2); boolean enabled = rs.getBoolean(3); UserInfo user = new UserInfo(username1, password, enabled, true, true, true, AuthorityUtils.NO_AUTHORITIES); user.setSalt(rs.getString(4)); user.setId(rs.getInt(5)); user.setCompanyId(rs.getInt(6)); user.setName(rs.getString(7)); user.setLoginStat(rs.getInt(8)); user.setLoginDate(rs.getLong(9)); user.setLoginIP(rs.getString(10)); return user; } ); } catch (Exception e) { e.printStackTrace(); } return null; } }
spring Security 调试的时候用到BasicAuthenticationFilter
package com.framework.security; import com.framework.db.BaseDao; import org.springframework.stereotype.Repository; @Repository("customUserDao") public class CustomUserDao extends BaseDao { public CustomUserDao() { super(Object.class); } }
基于框架的BaseDao
@Repository("baseDao") public class BaseDao<T> implements BaseDaoImp<T> { Logger log1 = LoggerFactory.getLogger(BaseDao.class); @Resource(name="jdbcTemplate") private JdbcTemplate jdbcTemplate; public JdbcTemplate getJdbcTemplate(){ return this.jdbcTemplate; } private Class<T> entityClass; public BaseDao(){} public BaseDao(Class<T> entityClass) { this.entityClass = entityClass; } @Override <span style="white-space:pre"> </span>public <T1> List<T1> queryForList(String sql, Object[] args, RowMapper<T1> rowMapper) throws DataAccessException { <span style="white-space:pre"> </span>return jdbcTemplate.query(sql, args,rowMapper); <span style="white-space:pre"> </span>} }
package com.framework.security; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.User; import java.util.Collection; /**** * @author tzz * @功能描述 * @date 2016/5/3 * 修改人 修改时间 修改说明 ****/ public class UserInfo extends User { private int id; private int companyId;//所属公司 private int loginSystemId = 0;//当前登录系统ID private String name;//用户名称 private int loginStat;//登录状态 1:登录 2:未登陆 private String loginIP;//登录IP private long loginDate;//登录时间 private String salt;//盐值字段 public UserInfo(String username, String password, Collection<? extends GrantedAuthority> authorities) { super(username, password, authorities); } public UserInfo(String username, String password, boolean enabled, boolean accountNonExpired,
boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) { super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities); } public String getSalt() { return salt; } public void setSalt(String salt) { this.salt = salt; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getCompanyId() { return companyId; } public void setCompanyId(int companyId) { this.companyId = companyId; } public int getLoginSystemId() { return loginSystemId; } public void setLoginSystemId(int loginSystemId) { this.loginSystemId = loginSystemId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getLoginStat() { return loginStat; } public void setLoginStat(int loginStat) { this.loginStat = loginStat; } public String getLoginIP() { return loginIP; } public void setLoginIP(String loginIP) { this.loginIP = loginIP; } public long getLoginDate() { return loginDate; } public void setLoginDate(long loginDate) { this.loginDate = loginDate; } }