序:这里主要对springmvc 项目中用spring-security和shiro两种连接LDAP的配置做说明
用来实现ldap对用户登录及权限的管理
一:spring security方式
(1)配置web.xml和导jar包:这里用maven 导入(spring-ldap-core spring-ldap-core-tiger spring-security-ldap spring-security-core spring-security-web spring-security-config spring-security-taglibs,这些都是1.31版本的jar)
可能有些包不用,但是我都加了 (礼多人不怪)
在web.xml里加入如下
(2).配置spring-security文件
xmlns:s="http://www.springframework.org/schema/security" 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.xsd">
access="IS_AUTHENTICATED_ANONYMOUSLY" />
//删除session中存储的错误提示
这个验证码具体怎么生成的这里不做说明
shiroFilter
org.springframework.web.filter.DelegatingFilterProxy
targetFilterLifecycle
true
shiroFilter
/*
group-search-filter="member={0}" group-search-base="ou=groups"
user-search-base="ou=people" user-search-filter="uid={0}" />
class="org.springframework.security.web.access.ExceptionTranslationFilter">
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
class="org.springframework.security.web.session.ConcurrentSessionFilter">
class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
class="org.springframework.security.ldap.authentication.BindAuthenticator">
class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
(3) 自定义拦截器com.zqgame.util.MySpecialAuthenticationFilter
这个拦截器就是做ldap登录认证的,里面包括了一些用户输入信息正确性判断和验证码判断(所有不能登录情况都是异常捕获)AuthenticationServiceException会根据上面的配置文件中登录错误的配置而跳转
package com.zqgame.util;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
public class MySpecialAuthenticationFilter extends AbstractAuthenticationProcessingFilter{
public MySpecialAuthenticationFilter() {
super("/auth");//这个auth就是外面要访问这个拦截器的入口
}
public MySpecialAuthenticationFilter(String defaultFilterProcessesUrl) {
super("/auth");
}
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password";
private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
HttpSession session = request.getSession();
String username = obtainUsername(request);
String password = obtainPassword(request);
String catchImage = request.getParameter("captcha");//验证码
//判断用户名登录密码是否为空
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
session.setAttribute("loginError", "请输入用户名或者密码!");
throw new AuthenticationServiceException("j_username or j_password is not null!"); //跳转到login_error下
}
// 从session中获得验证码,与用户输入的验证码做比较
String sessionCaptcha = (String) session.getAttribute(Constant.CAPTCHA);
if (StringUtils.isEmpty(catchImage) || StringUtils.isEmpty(sessionCaptcha)) {
session.setAttribute("loginError", "验证码为空!");
throw new AuthenticationServiceException("the session captcha is not null!");//跳转到login_error下
}
session.removeAttribute(Constant.CAPTCHA);// 清空Sesion里的验证码
//验证码输入校验
if (!sessionCaptcha.equalsIgnoreCase(catchImage)) {
session.setAttribute("loginError", "验证码输入错误!");
throw new AuthenticationServiceException("the captcha is error!");//跳转到login_error下
}
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
username, password);
setDetails(request, authRequest);
Authentication authen = null;
//执行ldap的登录验证
try {
authen = this.getAuthenticationManager().authenticate(authRequest);
} catch (AuthenticationException failed) {
session.setAttribute("loginError", "用户名或密码错误!");
throw new AuthenticationServiceException("the captcha is error!");//跳转到login_error
}
session.setAttribute("managerSession", username);
return authen;
}
protected String obtainPassword(HttpServletRequest request) {
return request.getParameter(passwordParameter);
}
protected String obtainUsername(HttpServletRequest request) {
return request.getParameter(usernameParameter);
}
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
}
}
(4)登录Action类
package com.zqgame.controllers.admin;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.zqgame.common.Constant;
import com.zqgame.models.SignIn;
import com.zqgame.services.UserService;
import com.zqgame.util.Digest;
/**
* 后台登录控制器
* @author User
*/
@Controller
public class SessionsController{
/**
* 进入登录页面
* @return
*/
@RequestMapping(value = "/sign_in", method = RequestMethod.GET)
public String newForm(Model model) {
return "admin/sessions/new";
}
/**
* 登录错误
* @return
*/
@RequestMapping(value = "/login_error", method = RequestMethod.GET)
public String loginError(Model model) {
return "admin/sessions/new";
}
/**
* 退出登录 logout() 销毁会话
* @param request
* @return
*/
@RequestMapping(value = "signout")
public void signOut(HttpServletRequest request, HttpServletResponse response) {
try {
SecurityContextLogoutHandler securityLogout = new SecurityContextLogoutHandler();
securityLogout.logout(request, response, null);
request.getRequestDispatcher(
"WEB-INF/views/admin/sessions/loginout.jsp").forward(
request, response);
} catch (Exception e) {
e.printStackTrace();
}
}
}
(5)登录jsp页面form部分
用户:
密码:
验证码:
这个验证码具体怎么生成的这里不做说明
登 录
上面就是整个LDAP与spring-security的配置了,当然这里只是我自己的处理方式,可能还有很多不好的地方,希望拍砖
二.Shiro 方式
(1)配置web.xml和导包(shiro-core shiro-web shiro-spring cglib-nodep 版本1.2.0)
Web.xml里加入
(2)Shiro配置文件(文档里有注释,这个配置文件基本上不用改啥)
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-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
/sign_in = anon
/admin/** = authc
/sign_up = anon
/captcha-p_w_picpath = anon
/sessions/** = anon
(3)登录action(这里action不用那么麻烦,所以这里就把登录的action和退出的action写上吧)
/*执行登录*/
public String create(@Valid SignIn signIn, BindingResult result, HttpSession session, Model model) {
if (result.hasErrors()) {
model.addAttribute("loginError", "请输入内容!");
model.addAttribute("signIn", signIn);
return "admin/sessions/new";
}
//从session中获得验证码
String sessionCaptcha = (String) session.getAttribute(Constant.CAPTCHA);
if(StringUtils.isEmpty(sessionCaptcha)) {
model.addAttribute("loginError", "session里的验证码为空!");
return "admin/sessions/new";
}
session.removeAttribute(Constant.CAPTCHA);//清空验证码
if(!sessionCaptcha.equalsIgnoreCase(signIn.getCaptcha())) {
model.addAttribute("loginError", "验证码输入错误!");
return "admin/sessions/new";
}
/*shiro执行ldap登录认证*/
UsernamePasswordToken token = new UsernamePasswordToken(signIn.getUsername(), signIn.getPassword());
token.setRememberMe(true);
Subject currentUser = SecurityUtils.getSubject();
try {
currentUser.login(token);
session.setAttribute(Constant.MANAGER_SESSION, signIn.getUsername());
}catch (Exception ice) {
result.reject("mismatch.signIn.password");
//password didn't match, try again?
}
if (currentUser.isAuthenticated()) {//登录成功进入主页
return "redirect:/body/adminmain";
}
model.addAttribute("loginError", "您输入的用户名或密码错误!");
return "admin/sessions/new";
}
/**
* 退出登录
* logout() 销毁回话
* @return
*/
@RequestMapping(value = "signout", method = RequestMethod.GET)
public void signOut(HttpServletRequest request, HttpServletResponse response) {
SecurityUtils.getSubject().logout();
try {
request.getRequestDispatcher("WEB-INF/views/admin/sessions/loginout.jsp").forward(request, response);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
到此两种方式都可以使用了,至于那个配置文件,可以把他放到web.xml里加载就行,就跟加载spring的文件一样就行
另:ldap本身的性质还在研究,不会哦
转载于:https://blog.51cto.com/3131854/1149082