赞
踩
Security3 安全架构 这里主要说的就是spring-security.xml 配置 因为网上这个资料确实很少
首先 pom
org.springframework.security 的包 我现在版本是3.1.4的 注意依赖都要导入的 包名就不写了!
web.xml
security 的过滤器链
- <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>
现在开始正题
spring-security.xml 配置 这个配置主要是用来重写attemptAuthentication方法的 这个是重点
- <http auto-config="true" use-expressions="true" access-denied-page="/403.jsp" >
- <!--login-processing-url 参数为登录的提交请求url -->
- <form-login login-processing-url="/home" login-page="/doctorLogin" always-use-default-target="false" default-target-url="/"/>
- <intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
- <logout invalidate-session="true" logout-success-url="/doctorLogin" logout-url="/logout"/> <!--退出登录-->
- <custom-filter before="FORM_LOGIN_FILTER" ref="verificationLogin"></custom-filter> <!--自定义拦截器 before 之前 FORM_LOGIN_FILTER 登录拦截-->
- <session-management>
- <concurrency-control max-sessions="1" error-if-maximum-exceeded="false" expired-url="/doctorLogin?error=2"/><!--只允许单线登录-->
- </session-management>
- </http>
- <beans:bean id="verificationLogin" class="com.hearing.cloud.background.loginFilter.LoginFilterAuthentication"> <!--登录拦截器-->
- <beans:property name="authenticationManager" ref="authenticationManager"/> <!--身份验证 必须的-->
- <beans:property name="authenticationSuccessHandler" ref="SuccessHandler" /> <!--验证通过 必须的-->
- <beans:property name="authenticationFailureHandler" ref="FailureHandler" /> <!--验证失败 必须的-->
- </beans:bean>
- <authentication-manager alias="authenticationManager"> <!--身份验证-->
- <authentication-provider user-service-ref="userDaoImpl"> <!--用户数据查询-->
- </authentication-provider>
- </authentication-manager>
- <beans:bean id="SuccessHandler" class="com.hearing.cloud.background.loginFilter.LoginSuccessHandler"></beans:bean> <!--验证通过逻辑-->
- <beans:bean id="FailureHandler" class="com.hearing.cloud.background.loginFilter.LoginFailureHandler"></beans:bean> <!--验证失败逻辑-->

//UsernamePasswordAuthenticationFilter的实现 重写 attemptAuthentication方法 逻辑随意修改
- package com.hearing.cloud.background.loginFilter;
-
- import com.hearing.cloud.background.model.OrdinaryUser;
- import com.hearing.cloud.background.model.User;
- import com.hearing.cloud.background.service.IOrdinaryUserManager;
- import com.hearing.cloud.background.service.IUserManager;
- import com.hearing.cloud.background.util.ActionUtil;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.security.authentication.AuthenticationServiceException;
- import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
- import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
- import org.springframework.security.core.Authentication;
- import org.springframework.security.core.AuthenticationException;
- import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
- import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
- import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
- import org.springframework.util.Assert;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.util.Map;
-
- //这里一般都是继承UsernamePasswordAuthenticationFilter 但是 我这里没有继承他 我继承了他爷爷 AbstractAuthenticationProcessingFilter
- public class LoginFilterAuthentication extends AbstractAuthenticationProcessingFilter {
-
-
- public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";
- public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password";
- /** @deprecated */
- @Deprecated
- public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";
- private String usernameParameter = "j_username";
- private String passwordParameter = "j_password";
- private boolean postOnly = true;
- private SessionAuthenticationStrategy sessionStrategy = new NullAuthenticatedSessionStrategy();
- //继承爷爷的原因是 我重新构造这个参数, 默认的是 /j_spring_security_check 我认为太丑
- public LoginFilterAuthentication() {
- super("/home");
- }
- @Autowired
- private IOrdinaryUserManager ordinaryUserManager;
- @Autowired
- private IUserManager iUserManager;
- @Autowired
- private ShaPasswordEncoder shaPasswordEncoder;
- public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
- if (this.postOnly &&!request.getMethod().equals("POST")) {
- throw new AuthenticationServiceException(
- "Authentication method not supported: " + request.getMethod());
- }
- UsernamePasswordAuthenticationToken authRequest=null;
- //前端的选择,0是用户名登录, 1是验证码登录
- Map<String,String> map = ActionUtil.getParameters(request);
- String selects=map.get("selects");
-
- if("0".equals(selects)){ //正常登陆 因为我们没有在xml中配置加密,所以我们手动加密,更灵活一些
- authRequest = new UsernamePasswordAuthenticationToken(账号, 密码);
- }else{ //电话号码登录 密码就不用加密了 直接登录
- //验证码对比结果
- boolean falg=true;
- if(falg) { //验证通过
- authRequest = new UsernamePasswordAuthenticationToken(账号, 密码);
- }else{//验证失败 我们要手动抛出一个异常,在后面的验证失败类中去捕获
- authRequest = new UsernamePasswordAuthenticationToken("", "");
- throw new AuthenticationServiceException("验证码错误");
- }
- request.getSession().removeAttribute("phone");
- }
- // Allow subclasses to set the "details" property
- setDetails(request, authRequest);
- // 执行校验(使用DaoAuthenticationProvider进行校验)
- return this.getAuthenticationManager().authenticate(authRequest);
- }
-
-
-
- protected String obtainPassword(HttpServletRequest request) {
- return request.getParameter(this.passwordParameter);
- }
-
- protected String obtainUsername(HttpServletRequest request) {
- return request.getParameter(this.usernameParameter);
- }
-
- protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
- authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
- }
-
- public void setUsernameParameter(String usernameParameter) {
- Assert.hasText(usernameParameter, "Username parameter must not be empty or null");
- this.usernameParameter = usernameParameter;
- }
-
- public void setPasswordParameter(String passwordParameter) {
- Assert.hasText(passwordParameter, "Password parameter must not be empty or null");
- this.passwordParameter = passwordParameter;
- }
-
- public void setPostOnly(boolean postOnly) {
- this.postOnly = postOnly;
- }
-
-
-
-
- }

//查询用户的实现 实现 UserDetailsService的 loadUserByUsername方法 返回一个UserDetails
- @Repository(value = "userDaoImpl")
- public class UserDaoImpl extends GenericDaoHibernate<User, String> implements IUserDao, UserDetailsService {
-
- /**
- * 用户登录
- */
- @SuppressWarnings({"deprecation", "rawtypes"})
- public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
- {
- //逻辑我就不写了 你们想怎么写就怎么写,记得查询出来的 user 转换成 UserDetails
- }
- }
//验证成功的方法 需要继承SimpleUrlAuthenticationSuccessHandler和实现AuthenticationSuccessHandler接口
- package com.hearing.cloud.background.loginFilter;
-
-
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.security.core.Authentication;
- import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
- import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
- import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
- import org.springframework.security.web.savedrequest.RequestCache;
- import org.springframework.security.web.savedrequest.SavedRequest;
- import org.springframework.util.StringUtils;
-
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
-
- public class LoginSuccessHandler extends SimpleUrlAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
- //我重写的目的 1.主要是这个位置 因为我要访问我的 跳转首页方法的逻辑接口
- //2.是如果不改这里 登录会有两个后果,1.登录后关闭页面,在次打开,页面会显示路径无法加载,2.
- //第一次登录成功跳转页面是你首页加载的第一个js页面而不是首页,请认真对待
- @Value("/")
- private String defaultTargetUrl;
-
- private RequestCache requestCache = new HttpSessionRequestCache();
- @Override
- public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
- SavedRequest savedRequest = this.requestCache.getRequest(request, response);
- if(savedRequest == null) {
- super.onAuthenticationSuccess(request, response, authentication);
- } else {
- String targetUrlParameter = this.getTargetUrlParameter();
- if(!this.isAlwaysUseDefaultTargetUrl() && (targetUrlParameter == null || !StringUtils.hasText(request.getParameter(targetUrlParameter)))) {
- this.clearAuthenticationAttributes(request);
- this.logger.debug("Redirecting to DefaultSavedRequest Url: " + defaultTargetUrl);
- this.getRedirectStrategy().sendRedirect(request, response, defaultTargetUrl);
- } else {
- this.requestCache.removeRequest(request, response);
- super.onAuthenticationSuccess(request, response, authentication);
- }
- }
- }
- public void setRequestCache(RequestCache requestCache) {
- this.requestCache = requestCache;
- }
- }

//验证失败 需要实现AuthenticationFailureHandler 接口
- package com.hearing.cloud.background.loginFilter;
-
-
- import org.springframework.security.core.AuthenticationException;
- import org.springframework.security.web.DefaultRedirectStrategy;
- import org.springframework.security.web.RedirectStrategy;
- import org.springframework.security.web.authentication.AuthenticationFailureHandler;
- import org.springframework.security.web.util.UrlUtils;
- import org.springframework.util.Assert;
-
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import javax.servlet.http.HttpSession;
- import java.io.IOException;
-
-
- public class LoginFailureHandler implements AuthenticationFailureHandler {
-
- private String defaultFailureUrl;
- private boolean forwardToDestination = false;
- private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
- private boolean allowSessionCreation = true;
-
- public LoginFailureHandler() {
- }
-
- public LoginFailureHandler(String defaultFailureUrl) {
- this.setDefaultFailureUrl(defaultFailureUrl);
- }
-
- public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
- if(this.defaultFailureUrl == null) {
- if("验证码错误".equals(e.getMessage())){
- redirectStrategy.sendRedirect(request, response, "/doctorLogin?error=3");
- }else{
- redirectStrategy.sendRedirect(request, response, "/doctorLogin?error=1");
- }
- } else {
- this.saveException(request, e);
- if(this.forwardToDestination) {
- request.getRequestDispatcher(this.defaultFailureUrl).forward(request, response);
- } else {
- this.redirectStrategy.sendRedirect(request, response, this.defaultFailureUrl);
- }
- }
- }
- public void setDefaultFailureUrl(String defaultFailureUrl) {
- Assert.isTrue(UrlUtils.isValidRedirectUrl(defaultFailureUrl), "\'" + defaultFailureUrl + "\' is not a valid redirect URL");
- this.defaultFailureUrl = defaultFailureUrl;
- }
- protected final void saveException(HttpServletRequest request, AuthenticationException exception) {
- if(this.forwardToDestination) {
- request.setAttribute("SPRING_SECURITY_LAST_EXCEPTION", exception);
- } else {
- HttpSession session = request.getSession(false);
- if(session != null || this.allowSessionCreation) {
- request.getSession().setAttribute("SPRING_SECURITY_LAST_EXCEPTION", exception);
- }
- }
-
- }
- protected boolean isUseForward() {
- return this.forwardToDestination;
- }
-
- public void setUseForward(boolean forwardToDestination) {
- this.forwardToDestination = forwardToDestination;
- }
-
- protected boolean isAllowSessionCreation() {
- return this.allowSessionCreation;
- }
-
- public void setAllowSessionCreation(boolean allowSessionCreation) {
- this.allowSessionCreation = allowSessionCreation;
- }
-
-
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。