- 浏览: 52075 次
- 性别:
- 来自: 上海
最新评论
-
qiao000_000:
我是Flex新手,我参照你的例子写了一下,发现只要在web.x ...
flex向struts2(action)传输数据
想给自己的程序加点安全控制,网上查了一下,说Spring Security是时下最流行,与spring结合的最好的安全框架,就决定去试一下。
使用的Spring Security版本是 3.0.5,它对Spring的版本是有要求的,Spring的版本必须在3.0以上,于是更新了下Spring环境,去官网下一个就行了,我用的是3.0.5版本号与Spring Security的版本正好相同。
Sping3本质上与Spring2没有什么区别,配置文件也不用动,主要就是Spring原来的核心包被拆成了小块,所有的功能现在都可以灵活的添加了。话虽如此,但其实也不是把所有的dist目录下的包全导进去就行了,网上查了一下,除了下面两个包:
org.springframework.web.struts-3.0.5.RELEASE.jar
org.springframework.web.portlet-3.0.5.RELEASE.jar
不要导入,另外还要添加一个日志相关包commons-logging和一个aopalliance的包就可以正常运作了。
======================================================================
接下来我们正式进入Spring Security3的配置
我的数据库结构不同于"参考手册"上的默认配置,都是用Hibernate进行映射构建的,以下是类的代码:
Ⅰ.Account类存储用户的信息
Ⅱ.Authorities对应Account中的grantedAuthorities属性,使用联合主键,有两个class文件共同实现
1.配置web.xml文件,照着参考文档我们添加如下几个标签
2.用Spring配置Spring Security,我写了两个文件进行配置
第一个用了命名空间,主要配置Spring Security的主体
另一个用来配置其中用到的注入类的声明
3.可以看出来,上面有些注入的类是我自己自定义的,为了让我的数据结构能够让Spring Security识别,我对如下几个默认组件进行了修改,然后添加到了框架中,下面附上代码
MyDaoAuthenticationProvider
AccountJDBCImpl
页面的制作,可以自己添加几个简单的进行尝试,注意login表单里面用户名的name要用j_username,password的name要用j_password,action的url要写"<%=path %>/j_spring_security_check"
经过如上配置,所有的role_开头的资源都会被保护,需要用户登录,且拥有"ROLE_USER"的权限才可以查阅,我们可以自己去数据库添加用户添加权限来进行登录。
我的主要参考是Spring Security-3.0.1中文官方文档,然后查看Spring Security包里面的源码会有很大的帮助。
使用的Spring Security版本是 3.0.5,它对Spring的版本是有要求的,Spring的版本必须在3.0以上,于是更新了下Spring环境,去官网下一个就行了,我用的是3.0.5版本号与Spring Security的版本正好相同。
Sping3本质上与Spring2没有什么区别,配置文件也不用动,主要就是Spring原来的核心包被拆成了小块,所有的功能现在都可以灵活的添加了。话虽如此,但其实也不是把所有的dist目录下的包全导进去就行了,网上查了一下,除了下面两个包:
org.springframework.web.struts-3.0.5.RELEASE.jar
org.springframework.web.portlet-3.0.5.RELEASE.jar
不要导入,另外还要添加一个日志相关包commons-logging和一个aopalliance的包就可以正常运作了。
======================================================================
接下来我们正式进入Spring Security3的配置
我的数据库结构不同于"参考手册"上的默认配置,都是用Hibernate进行映射构建的,以下是类的代码:
Ⅰ.Account类存储用户的信息
package cn.com.jusesgod.domain.security; import java.util.Collection; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.OneToMany; import javax.persistence.Transient; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; @Entity public class Account implements UserDetails{ /** * */ private static final long serialVersionUID = 5275764647347461532L; private String username; //用户名 private String password; //密码 private boolean enable; //是否可用 private Set<Authorities> grantedAuthorities; //表示用户所拥有的权限 private int total; //玩这个游戏的总局数 private int win; //赢的局数 private int lose; //输的局数 private int flee; //逃走的局数 public Account(){} public Account(String username,String password){ this.username = username; this.password = password; this.total = 0; this.win = 0; this.lose = 0; this.flee = 0; } public Account(String username,String password,int total,int win,int lose,int flee, Collection<GrantedAuthority> authorities){ this.username = username; this.password = password; this.total = total; this.win = win; this.lose = lose; this.flee = flee; this.enable = true; grantedAuthorities = new HashSet<Authorities>(); for(GrantedAuthority t : authorities){ grantedAuthorities.add(new Authorities(this.username,t.getAuthority())); } } public void strat(){ total += 1; } public void setFlee(int flee) { this.flee = flee; } public void setLose(int lose) { this.lose = lose; } public void setTotal(int total) { this.total = total; } public void setWin(int win) { this.win = win; } public void win(){ win += 1; } public void lose(){ lose += 1; } public void flee(){ flee += 1; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Id public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public int getTotal() { return total; } public int getWin() { return win; } public int getLose() { return lose; } public int getFlee() { return flee; } @OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER) //FetchType.EAGER表示立刻加载 @JoinTable(name="authorities", joinColumns=@JoinColumn(name="username")) public Set<Authorities> getGrantedAuthorities() { return grantedAuthorities; } @Transient public Set<GrantedAuthority> getAuthorities() { Set<GrantedAuthority> ga = new HashSet<GrantedAuthority>(); for(Authorities temp : grantedAuthorities){ ga.add(temp); } return ga; } public void setGrantedAuthorities(Set<Authorities> authorities) { this.grantedAuthorities = authorities; } public boolean isEnable() { return enable; } public void setEnable(boolean enable) { this.enable = enable; } @Transient public boolean isAccountNonExpired() { // TODO Auto-generated method stub return true; } @Transient public boolean isAccountNonLocked() { // TODO Auto-generated method stub return true; } @Transient public boolean isCredentialsNonExpired() { // TODO Auto-generated method stub return true; } @Transient public boolean isEnabled() { return enable; } }
Ⅱ.Authorities对应Account中的grantedAuthorities属性,使用联合主键,有两个class文件共同实现
package cn.com.jusesgod.domain.security; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.IdClass; import org.springframework.security.core.GrantedAuthority; @Entity @IdClass(AuthoritiesPK.class) public class Authorities implements GrantedAuthority { private String username; private String authority; public Authorities(){} public Authorities(String username,String authority){ this.username = username; this.authority = authority; } public void setAuthority(String authority) { this.authority = authority; } @Id public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @Id public String getAuthority() { return authority; } }
package cn.com.jusesgod.domain.security; import java.io.Serializable; import javax.persistence.Embeddable; @Embeddable public class AuthoritiesPK implements Serializable { private String username; private String authority; public AuthoritiesPK(){} public AuthoritiesPK(String username,String authority){ this.username = username; this.authority = authority; } public void setAuthority(String authority) { this.authority = authority; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getAuthority() { return authority; } }
1.配置web.xml文件,照着参考文档我们添加如下几个标签
<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>
2.用Spring配置Spring Security,我写了两个文件进行配置
第一个用了命名空间,主要配置Spring Security的主体
<?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-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd"> <http auto-config="true" access-denied-page="/error.html"> <intercept-url pattern="/login.*" filters="none"/> <intercept-url pattern="/role_*" access="ROLE_USER"/> <form-login login-page="/login.html" default-target-url="/role_hall.html" authentication-failure-url="/login.jsp"/> <custom-filter ref="authenticationFilter" before="FORM_LOGIN_FILTER"/> <!-- 第二次登录阻止,用户会被转发到 form-login 标签里定义的 authentication-failure-url 的地址 如果是form-base登录,用户会被转发到 session-management 中 session-authention-error-url 的地址 session-fixation-protection 防止Session固定攻击(2.3.3.3) -migrateSession 创建一个新的session,把原来session中所有属性复制到新session中。这是默认值 -none 什么也不做 -newSession 创建一个新的"干净的"session,不会复制session中的数据。 --> <session-management session-fixation-protection="migrateSession" invalid-session-url="/error.html"> <!-- max-session error-if-maxinum-exceeded --> <concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/> </session-management> </http> <authentication-manager> <authentication-provider user-service-ref="accoutJDBCImpl"> </authentication-provider> </authentication-manager> <global-method-security secured-annotations="enabled" jsr250-annotations="enabled"></global-method-security> </beans:beans>
另一个用来配置其中用到的注入类的声明
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:security="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd 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.0.xsd"> <bean id="authenticationFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"> <property name="authenticationManager" ref="authenticationManager"></property> <property name="filterProcessesUrl" value="/j_spring_security_check"></property> </bean> <bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager"> <property name="providers"> <list> <ref local="daoAuthenticationProvider"/> </list> </property> </bean> <bean id="daoAuthenticationProvider" class="cn.com.jusesgod.authentication.provider.MyDaoAuthenticationProvider"> <property name="userDetailsService" ref="accoutJDBCImpl"></property> </bean> <bean id="accoutJDBCImpl" class="cn.com.jusesgod.service.impl.AccountJDBCImpl"> <property name="dataSource" ref="dataSource"></property> </bean> <bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.web.authentication.AuthenticationProcessingFilterEntryPoint"> <property name="loginFormUrl" value="/login"></property> </bean> </beans>
3.可以看出来,上面有些注入的类是我自己自定义的,为了让我的数据结构能够让Spring Security识别,我对如下几个默认组件进行了修改,然后添加到了框架中,下面附上代码
MyDaoAuthenticationProvider
package cn.com.jusesgod.authentication.provider; import org.springframework.dao.DataAccessException; import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider; import org.springframework.security.authentication.dao.SaltSource; import org.springframework.security.authentication.encoding.PasswordEncoder; import org.springframework.security.authentication.encoding.PlaintextPasswordEncoder; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.util.Assert; public class MyDaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider { private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder(); private SaltSource saltSource; private UserDetailsService userDetailsService; private boolean includeDetailsObject = true; //~ Methods ======================================================================================================== protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { Object salt = null; if (this.saltSource != null) { salt = this.saltSource.getSalt(userDetails); } if (authentication.getCredentials() == null) { logger.debug("Authentication failed: no credentials provided"); throw new BadCredentialsException(messages.getMessage( "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), includeDetailsObject ? userDetails : null); } String presentedPassword = authentication.getCredentials().toString(); logger.debug("presentedPassword:" + presentedPassword); logger.debug("userDetails.getPassword():" + userDetails.getPassword()); System.out.println(presentedPassword); if (!passwordEncoder.isPasswordValid(userDetails.getPassword(), presentedPassword, salt)) { logger.debug("Authentication failed: password does not match stored value"); throw new BadCredentialsException(messages.getMessage( "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), includeDetailsObject ? userDetails : null); } } protected void doAfterPropertiesSet() throws Exception { Assert.notNull(this.userDetailsService, "A UserDetailsService must be set"); } protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { UserDetails loadedUser; try { loadedUser = this.getUserDetailsService().loadUserByUsername(username); } catch (DataAccessException repositoryProblem) { throw new AuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem); } if (loadedUser == null) { throw new AuthenticationServiceException( "UserDetailsService returned null, which is an interface contract violation"); } return loadedUser; } /** * Sets the PasswordEncoder instance to be used to encode and validate passwords. * If not set, {@link PlaintextPasswordEncoder} will be used by default. * * @param passwordEncoder The passwordEncoder to use */ public void setPasswordEncoder(PasswordEncoder passwordEncoder) { this.passwordEncoder = passwordEncoder; } protected PasswordEncoder getPasswordEncoder() { return passwordEncoder; } /** * The source of salts to use when decoding passwords. <code>null</code> * is a valid value, meaning the <code>DaoAuthenticationProvider</code> * will present <code>null</code> to the relevant <code>PasswordEncoder</code>. * * @param saltSource to use when attempting to decode passwords via the <code>PasswordEncoder</code> */ public void setSaltSource(SaltSource saltSource) { this.saltSource = saltSource; } protected SaltSource getSaltSource() { return saltSource; } public void setUserDetailsService(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } protected UserDetailsService getUserDetailsService() { return userDetailsService; } protected boolean isIncludeDetailsObject() { return includeDetailsObject; } /** * Determines whether the UserDetails will be included in the <tt>extraInformation</tt> field of a * thrown BadCredentialsException. Defaults to true, but can be set to false if the exception will be * used with a remoting protocol, for example. * * @deprecated use {@link org.springframework.security.authentication.ProviderManager#setClearExtraInformation(boolean)} */ public void setIncludeDetailsObject(boolean includeDetailsObject) { this.includeDetailsObject = includeDetailsObject; } }
AccountJDBCImpl
package cn.com.jusesgod.service.impl; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.springframework.context.ApplicationContextException; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.support.JdbcDaoSupport; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.SpringSecurityMessageSource; import org.springframework.security.core.authority.GrantedAuthorityImpl; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.util.Assert; import cn.com.jusesgod.domain.security.Account; /** * <tt>UserDetailsServiceRetrieves</tt> implementation which retrieves the user details * (username, password, enabled flag, and authorities) from a database using JDBC queries. * UserDetailsServiceRettrieves * 实现了如何去得到用用户的信息(username,password,enabled flag,和authorite)通过JDBC查询获取数据源 * * <h3>Default Schema</h3> * 默认的模式 * A default database schema is assumed, with two tables "users" and "authorities". * 一个默认的数据模式被设定,有两个表"user"和"authorities" * <h4>The Users table</h4> * User表 * This table contains the login name, password and enabled status of the user. * * <table> * <tr><th>Column</th></tr> * <tr><td>username</td></tr> * <tr><td>password</td></tr> * <tr><td>enabled</td></tr> * </table> * * <h4>The Authorities Table</h4> * Authorities表 * <table> * <tr><th>Column</th></tr> * <tr><td>username</td></tr> * <tr><td>authority</td></tr> * </table> * * If you are using an existing schema you will have to set the queries <tt>usersByUsernameQuery</tt> and * <tt>authoritiesByUsernameQuery</tt> to match your database setup * 如果你使用一个存在的模式,你必须设置查询方法"usersByUsernameQuery"和"authoritiesByUsernameQuery"去适应你的数据源设置 * (see {@link #DEF_USERS_BY_USERNAME_QUERY} and {@link #DEF_AUTHORITIES_BY_USERNAME_QUERY}). * 查看这两个变量会有帮助 * * <p> * In order to minimise backward compatibility issues, this implementation doesn't recognise the expiration of user * accounts or the expiration of user credentials. However, it does recognise and honour the user enabled/disabled * column. This should map to a <tt>boolean</tt> type in the result set (the SQL type will depend on the * database you are using). All the other columns map to <tt>String</tt>s. * 为了尽量减少向后兼容性的问题,这个实现不关心用户账户的期限或者用户证书的期限。而只关心注意用户是否可用(enable/disable列),这需要设置成一个 * boolean的类型在返回的设置里(在数据库保存的SQL属性取决于你的数据库)所有其他的属性使用String类型 * * <h3>Group Support</h3> * 组权限支持 * Support for group-based authorities can be enabled by setting the <tt>enableGroups</tt> property to <tt>true</tt> * (you may also then wish to set <tt>enableAuthorities</tt> to <tt>false</tt> to disable loading of authorities * directly). With this approach, authorities are allocated to groups and a user's authorities are determined based * on the groups they are a member of. The net result is the same (a UserDetails containing a set of * <tt>GrantedAuthority</tt>s is loaded), but the different persistence strategy may be more suitable for the * administration of some applications. * <p> * 对于支持组权限,我们需要设置enableGroups属性为true(你应当还希望去设置enableAuthorities为false去阻止导入authorities表中的权限设置) * 通过这种方法,权限被分成一组一组的,并且用户的权限被通过组的方法确定他们归属于那一个权限组。网络要求同样的(一个UserDetails包含 * 一个GrantedAuthority的设置被读取),但是不同的应用可能需要不同的持久化策略。 * * When groups are being used, the tables "groups", "group_members" and "group_authorities" are used. See * {@link #DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY} for the default query which is used to load the group authorities. * Again you can customize this by setting the <tt>groupAuthoritiesByUsernameQuery</tt> property, but the format of * the rows returned should match the default. * 当组权限被使用,表groups,group_members和group_authorities也被使用。参看DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY属性,了解 * 默认的组权限查询语句。 * 同样,你可以去自定义这个属性通过设置groupAuthoritiesByUsernameQuery属性,但是返回的结果列会被格式化成默认的形式。 * * @author Ben Alex * @author colin sampaleanu * @author Luke Taylor */ public class AccountJDBCImpl extends JdbcDaoSupport implements UserDetailsService { // ~ Static fields/initializers ===================================================================================== public static final String DEF_USERS_BY_USERNAME_QUERY = "select username,password,enable " + "from Account " + "where username = ?"; public static final String DEF_AUTHORITIES_BY_USERNAME_QUERY = "select username,authority " + "from Authorities " + "where username = ?"; public static final String DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY = "select g.id, g.group_name, ga.authority " + "from groups g, group_members gm, group_authorities ga " + "where gm.username = ? " + "and g.id = ga.group_id " + "and g.id = gm.group_id"; //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private String authoritiesByUsernameQuery; private String groupAuthoritiesByUsernameQuery; private String usersByUsernameQuery; private String rolePrefix = ""; private boolean usernameBasedPrimaryKey = true; private boolean enableAuthorities = true; private boolean enableGroups = false; //~ Constructors =================================================================================================== public AccountJDBCImpl() { usersByUsernameQuery = DEF_USERS_BY_USERNAME_QUERY; authoritiesByUsernameQuery = DEF_AUTHORITIES_BY_USERNAME_QUERY; groupAuthoritiesByUsernameQuery = DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY; } //~ Methods ======================================================================================================== /** * Allows subclasses to add their own granted authorities to the list to be returned in the <tt>UserDetails</tt>. * 允许子类添加他们自己的授权权限到列表里,在UserDetails里面被返回。 * * @param username the username, for use by finder methods * @param authorities the current granted authorities, as populated from the <code>authoritiesByUsername</code> * mapping */ protected void addCustomAuthorities(String username, List<GrantedAuthority> authorities) { } public String getUsersByUsernameQuery() { return usersByUsernameQuery; } protected void initDao() throws ApplicationContextException { //确保两个权限模式必有一个在使用 Assert.isTrue(enableAuthorities || enableGroups, "Use of either authorities or groups must be enabled"); } public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { 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"), username); } UserDetails user = users.get(0); // contains no GrantedAuthority[] Set<GrantedAuthority> dbAuthsSet = new HashSet<GrantedAuthority>(); if (enableAuthorities) { dbAuthsSet.addAll(loadUserAuthorities(user.getUsername())); } if (enableGroups) { dbAuthsSet.addAll(loadGroupAuthorities(user.getUsername())); } List<GrantedAuthority> dbAuths = new ArrayList<GrantedAuthority>(dbAuthsSet); addCustomAuthorities(user.getUsername(), dbAuths); 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"), username); } System.out.println("dbAuths:" + dbAuths.get(0).getAuthority()); return createUserDetails(username, user, dbAuths); } /** * Executes the SQL <tt>usersByUsernameQuery</tt> and returns a list of UserDetails objects. * There should normally only be one matching user. */ protected List<UserDetails> loadUsersByUsername(String username) { return getJdbcTemplate().query(usersByUsernameQuery, new String[] {username}, new RowMapper<UserDetails>() { public UserDetails mapRow(ResultSet rs, int rowNum) throws SQLException { String username = rs.getString(1); String password = rs.getString(2); return new Account(username,password,0,0,0,0,new HashSet<GrantedAuthority>()); } }); } /** * Loads authorities by executing the SQL from <tt>authoritiesByUsernameQuery</tt>. * * @return a list of GrantedAuthority objects for the user */ protected List<GrantedAuthority> loadUserAuthorities(String username) { return getJdbcTemplate().query(authoritiesByUsernameQuery, new String[] {username}, new RowMapper<GrantedAuthority>() { public GrantedAuthority mapRow(ResultSet rs, int rowNum) throws SQLException { String roleName = rolePrefix + rs.getString(2); logger.debug("row authorities:" + roleName + " to " + rs.getString(1)); GrantedAuthorityImpl authority = new GrantedAuthorityImpl(roleName); return authority; } }); } /** * Loads authorities by executing the SQL from <tt>groupAuthoritiesByUsernameQuery</tt>. * * @return a list of GrantedAuthority objects for the user */ protected List<GrantedAuthority> loadGroupAuthorities(String username) { return getJdbcTemplate().query(groupAuthoritiesByUsernameQuery, new String[] {username}, new RowMapper<GrantedAuthority>() { public GrantedAuthority mapRow(ResultSet rs, int rowNum) throws SQLException { String roleName = getRolePrefix() + rs.getString(3); GrantedAuthorityImpl authority = new GrantedAuthorityImpl(roleName); return authority; } }); } /** * Can be overridden to customize the creation of the final UserDetailsObject which is * returned by the <tt>loadUserByUsername</tt> method. * * @param username the name originally passed to loadUserByUsername * @param userFromUserQuery the object returned from the execution of the * @param combinedAuthorities the combined array of authorities from all the authority loading queries. * @return the final UserDetails which should be used in the system. */ protected UserDetails createUserDetails(String username, UserDetails userFromUserQuery, List<GrantedAuthority> combinedAuthorities) { String returnUsername = userFromUserQuery.getUsername(); if (!usernameBasedPrimaryKey) { returnUsername = username; } logger.debug("username = " + returnUsername); logger.debug("password = " + userFromUserQuery.getPassword()); return new Account(returnUsername, userFromUserQuery.getPassword(), 0, 0, 0, 0,combinedAuthorities); } /** * Allows the default query string used to retrieve authorities based on username to be overridden, if * default table or column names need to be changed. The default query is {@link * #DEF_AUTHORITIES_BY_USERNAME_QUERY}; when modifying this query, ensure that all returned columns are mapped * back to the same column names as in the default query. * * @param queryString The SQL query string to set */ public void setAuthoritiesByUsernameQuery(String queryString) { authoritiesByUsernameQuery = queryString; } protected String getAuthoritiesByUsernameQuery() { return authoritiesByUsernameQuery; } /** * Allows the default query string used to retrieve group authorities based on username to be overridden, if * default table or column names need to be changed. The default query is {@link * #DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY}; when modifying this query, ensure that all returned columns are mapped * back to the same column names as in the default query. * * @param queryString The SQL query string to set */ public void setGroupAuthoritiesByUsernameQuery(String queryString) { groupAuthoritiesByUsernameQuery = queryString; } /** * Allows a default role prefix to be specified. If this is set to a non-empty value, then it is * automatically prepended to any roles read in from the db. This may for example be used to add the * <tt>ROLE_</tt> prefix expected to exist in role names (by default) by some other Spring Security * classes, in the case that the prefix is not already present in the db. * * @param rolePrefix the new prefix */ public void setRolePrefix(String rolePrefix) { this.rolePrefix = rolePrefix; } protected String getRolePrefix() { return rolePrefix; } /** * If <code>true</code> (the default), indicates the {@link #getUsersByUsernameQuery()} returns a username * in response to a query. If <code>false</code>, indicates that a primary key is used instead. If set to * <code>true</code>, the class will use the database-derived username in the returned <code>UserDetails</code>. * If <code>false</code>, the class will use the {@link #loadUserByUsername(String)} derived username in the * returned <code>UserDetails</code>. * * @param usernameBasedPrimaryKey <code>true</code> if the mapping queries return the username <code>String</code>, * or <code>false</code> if the mapping returns a database primary key. */ public void setUsernameBasedPrimaryKey(boolean usernameBasedPrimaryKey) { this.usernameBasedPrimaryKey = usernameBasedPrimaryKey; } protected boolean isUsernameBasedPrimaryKey() { return usernameBasedPrimaryKey; } /** * Allows the default query string used to retrieve users based on username to be overridden, if default * table or column names need to be changed. The default query is {@link #DEF_USERS_BY_USERNAME_QUERY}; when * modifying this query, ensure that all returned columns are mapped back to the same column names as in the * default query. If the 'enabled' column does not exist in the source database, a permanent true value for this * column may be returned by using a query similar to * <pre> * "select username,password,'true' as enabled from users where username = ?" * </pre> * * @param usersByUsernameQueryString The query string to set */ public void setUsersByUsernameQuery(String usersByUsernameQueryString) { this.usersByUsernameQuery = usersByUsernameQueryString; } protected boolean getEnableAuthorities() { return enableAuthorities; } /** * Enables loading of authorities (roles) from the authorities table. Defaults to true */ public void setEnableAuthorities(boolean enableAuthorities) { this.enableAuthorities = enableAuthorities; } protected boolean getEnableGroups() { return enableGroups; } /** * Enables support for group authorities. Defaults to false * @param enableGroups */ public void setEnableGroups(boolean enableGroups) { this.enableGroups = enableGroups; } }
页面的制作,可以自己添加几个简单的进行尝试,注意login表单里面用户名的name要用j_username,password的name要用j_password,action的url要写"<%=path %>/j_spring_security_check"
经过如上配置,所有的role_开头的资源都会被保护,需要用户登录,且拥有"ROLE_USER"的权限才可以查阅,我们可以自己去数据库添加用户添加权限来进行登录。
我的主要参考是Spring Security-3.0.1中文官方文档,然后查看Spring Security包里面的源码会有很大的帮助。
相关推荐
SSH(Struts2 + Spring + Hibernate)是一个经典的Java Web开发框架,用于构建高效、模块化且可维护的企业级应用程序。在这个项目中,我们将探讨如何将Spring Security集成到SSH项目中,实现基于数据库验证的用户...
SSH是Java Web开发中常见的三大框架,而Spring Security则是一个强大的安全框架,用于处理应用的安全性问题,如认证和授权。 【 Maven 】Maven是一个项目管理工具,它可以帮助开发者管理项目构建、依赖、版本控制等...
SSH框架,即Struts+Spring+Hibernate框架,是Java Web开发中的一种流行架构,它将三种技术结合在一起,各自承担不同的职责,共同构建出稳定、高效、易于维护的Web应用程序。 ### Spring在SSH框架中的核心角色 在...
SSH和Spring框架是Java开发中的两个重要工具,它们在企业级应用开发中占据了核心地位。SSH,是由Struts2、Spring和Hibernate三个框架组成的集成解决方案,而Spring则是一个全面的后端开发框架,包含了多种功能模块。...
SSH + Spring Security3.2例子
在本项目中,我们将探讨如何将Spring Security与SSH(Struts2、Spring、Hibernate)框架整合,以实现一个完整的基于数据库的用户认证和授权系统。 SSH是Java开发中常用的三大框架组合,它们各自负责不同的职责:...
SSH框架是指将Struts、Spring以及Hibernate这三个开源框架进行整合,以实现更加强大、灵活且可扩展的企业级应用开发。本文将详细介绍如何在MyEclipse 8.5环境下搭建基于Struts2.1、Spring3.0以及Hibernate3.3的SSH...
SSH框架,全称为Spring、Struts和Hibernate,是Java Web开发中的一个经典组合,用于构建高效、可维护的Web应用程序。这些框架各自负责不同的职责,Spring作为基础架构框架,Struts处理视图与控制,Hibernate则专注于...
总的来说,SSH+Spring Security+MySQL的结合提供了一套强大且灵活的解决方案,用于构建安全的Web应用程序,特别是对于需要用户登录权限控制的场景。通过合理的配置和开发,可以实现复杂的安全需求,保证系统数据的...
3. **配置整合**:在SSH项目中,我们需要在struts2的配置文件中添加Spring Security的过滤器链,如`<filter>`标签,以及在Spring的配置文件中定义Spring Security的相关bean,如`http`、`authentication-manager`等...
3. **Spring Security(原名Acegi Security)**:这是一个强大的安全框架,提供认证、授权等功能。在这个项目中,Spring Security负责用户的身份验证和权限控制。它可以根据用户的角色分配不同的访问权限,实现对...
SSH框架,全称为Spring、Struts2和Hibernate的组合,是Java Web开发中常见的三大开源框架集成。这个框架集合提供了模型-视图-控制器(MVC)架构模式,数据库持久化,以及强大的前端展示能力,使得开发者能高效地构建...
SSH框架,全称为Struts2、Spring和Hibernate的组合,是Java Web开发中常见的三大开源框架集成。这个压缩包文件"SSHdemo"提供了一个SSH框架搭建登录功能的示例,帮助开发者了解并实践如何整合这三个框架来构建一个...
SSH框架整合是Java Web开发中常见的一种技术栈,由Spring、Hibernate和Struts2三个开源框架组合而成。这个组合提供了一种高效、灵活且可扩展的解决方案,用于构建企业级的Web应用程序。以下是对SSH框架整合及其中...
总的来说,SSH框架整合是Java Web开发中的一个强大工具,它将Struts2的MVC设计模式、Spring的依赖注入和事务管理以及Hibernate的对象关系映射结合在一起,为开发人员提供了高效、稳定的开发环境。对于初学者而言,...
在实际开发中,SSH框架的使用不仅限于基本功能,还可以结合其他技术,如MyBatis、Spring Boot、Spring Data等,以适应不断变化的开发需求。SSH框架为Java Web开发提供了坚实的基础,是许多大型企业的首选技术栈。...
SSH框架,全称为Struts2、Spring和Hibernate的组合,是Java Web开发中常见的三大开源框架集成。这个“ssh框架纯净版”包含了这三个框架的基础组件和相关代码,旨在提供一个简洁、无多余依赖的开发环境。 1. **...
Java SSH 框架整合是Java开发中常见的一项技术,主要涉及Spring、Struts和Hibernate这三个开源框架。这些框架在企业级应用开发中扮演着重要角色,分别负责控制层、视图层和持久层的管理。下面将详细介绍SSH框架整合...
### SSH框架整合详细步骤(spring+struts2+hibernate) #### 一、整合概述 在现代Web应用开发中,SSH(Struts2、Spring、Hibernate)框架因其各自独特的功能和优势,常被组合使用以构建高效、稳定且易于维护的系统...