Skip to content

Commit

Permalink
重写登录认证
Browse files Browse the repository at this point in the history
  • Loading branch information
xwj-vic committed Mar 11, 2017
1 parent 78f3aa4 commit 2072d06
Show file tree
Hide file tree
Showing 14 changed files with 271 additions and 70 deletions.
10 changes: 5 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -166,26 +166,26 @@
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
<version>1.4.0-RC2</version>
</dependency>

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.3.2</version>
<version>1.4.0-RC2</version>
</dependency>

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
<version>1.4.0-RC2</version>
</dependency>

<!--添加ehcache-->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.3</version>
<artifactId>ehcache-core</artifactId>
<version>2.6.11</version>
</dependency>

<!-- 添加 shiro-ehcache 接口依赖-->
Expand Down
59 changes: 59 additions & 0 deletions src/main/java/exception/CustomExceptionResolver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package exception;

import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
* Created by xuweijie on 2017/3/10.
* 统一异常处理类
* 可以在controller方法、service方法、dao实现类中抛出异常
* 要求dao、service、controller遇到异常全部向上抛出异常,方法向 上抛出异常throws Exception
*/
public class CustomExceptionResolver implements HandlerExceptionResolver {

//前端控制器DispatcherServlet在进行HandlerMapping、
// 调用HandlerAdapter执行Handler过程中,如果遇到异常就会执行此方法
//参数中的handler是最终要执行的Handler,它的真实身份是HandlerMethod
//ex就是接受到的异常信息

public ModelAndView resolveException(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object handler, Exception ex) {

ex.printStackTrace();
/*统一异常处理代码
*针对系统自定义的CustomException异常,就可以直接从异常中获取异常信息,将异常处理在错误页面展示
*异常信息
* */
String message=null;
CustomException customException=null;

//如果ex是系统自定义的异常,我们就直接取出异常信息
if(ex instanceof CustomException){
customException= (CustomException) ex;
}else {
customException=new CustomException("未知错误");
}

//错误信息
message=customException.getMessage();
httpServletRequest.setAttribute("message",message);

try{
//转向到错误页面
httpServletRequest.getRequestDispatcher("/WEB-INF/jsp/error.jsp").forward(httpServletRequest,httpServletResponse);
}catch (ServletException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return new ModelAndView();
}
}
46 changes: 46 additions & 0 deletions src/main/java/filter/CustomFromAuthenticationFilter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package filter;

import com.google.code.kaptcha.Constants;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
* Created by xuweijie on 2017/3/10.
* shiro的表单过滤器:FormAuthenticationFilter,重写表单过滤器,实现先通过验证码验证再验证账户密码
*/
public class CustomFromAuthenticationFilter extends FormAuthenticationFilter{


@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest= (HttpServletRequest) request;
HttpSession session=httpServletRequest.getSession();
String verifyCode;
try{
verifyCode=httpServletRequest.getParameter("verifyCode").toUpperCase();
}catch (NullPointerException e){
verifyCode=null;
}
//判断验证码输入是否正确
if(verifyCode!=null && !verifyCode.equals(session.getAttribute(Constants.KAPTCHA_SESSION_KEY))){
//如果校验失败,将验证码错误的失败信息,通过shiroLoginFailure设置到request中
httpServletRequest.setAttribute("shiroLoginFailure","randomCodeError");
//拒绝访问,不再校验账号和密码
return true;
}
return super.onAccessDenied(request, response);
}

@Override
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
WebUtils.issueRedirect(request,response,getSuccessUrl());
return false;
}
}
2 changes: 1 addition & 1 deletion src/main/java/service/impl/ShiroUserServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class ShiroUserServiceImpl implements ShiroUserService {
@Autowired
private ShiroUserDao userDao;

public User queryUser(String username) {
public User queryUser(String username){
return userDao.queryByName(username);
}
}
15 changes: 12 additions & 3 deletions src/main/java/shiro/shirorealm/CustomRealm.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,26 @@
/**
* Created by xuweijie on 2017/3/3.
*/
public class CustomRealm extends AuthorizingRealm {
public class CustomRealm extends AuthorizingRealm{

@Autowired
private ShiroUserService userService;

//设置realm的名称
@Override
public void setName(String name) {
super.setName("customRealm");
}

//登录认证
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

String username= (String) authenticationToken.getPrincipal();
User user=userService.queryUser(username);
if(user==null){
User user= null;

user = userService.queryUser(username);

if(userService==null){
return null;
}
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username,user.getPassword(),
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/web/HomepageController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package web;

import entity.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

/**
* Created by xuweijie on 2017/3/11.
*/
@Controller
public class HomepageController {

@RequestMapping(value = "/homepage")
public String loginsuccess( Model model) throws Exception{
Subject subject= SecurityUtils.getSubject();
String username= (String) subject.getPrincipal();
model.addAttribute("username",username);
return "Homepage";
}
}
54 changes: 24 additions & 30 deletions src/main/java/web/LoginController.java
Original file line number Diff line number Diff line change
@@ -1,51 +1,45 @@
package web;

import com.google.code.kaptcha.Constants;
import entity.User;
import exception.CustomException;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;

/**
* Created by xuweijie on 2017/3/3.
*/
@Controller
public class LoginController {
public class LoginController{

@RequestMapping(value = "/login",method = RequestMethod.POST)
public String login(HttpServletRequest request, Model model){
CustomException customException=null;
String verifyCode=request.getParameter("verifyCode").toUpperCase();
String username=request.getParameter("username");
String password=request.getParameter("password");
//判断验证码输入是否正确
if(verifyCode.equals(request.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY))){
if((username!=null && password!=null)){
UsernamePasswordToken token=new UsernamePasswordToken(username,password);
Subject subject= SecurityUtils.getSubject();
try{
subject.login(token);
}catch (AuthenticationException e){
customException=new CustomException(e.getMessage());
}
if( subject.isAuthenticated()){
subject.logout();
model.addAttribute("username",username);
return "/loginsuccess";
}else {
model.addAttribute("exception",customException.getMessage());
return "/refuse";
}
@RequestMapping("/login")
public String login(HttpServletRequest request,Model model) throws Exception{
//如果登录失败从request中获取认证异常信息,shiroLoginFailure就是shiro异常类的全限定名
String exceptionClassName= (String) request.getAttribute("shiroLoginFailure");
//根据shiro返回的异常类路径判断,抛出指定异常信息
if(exceptionClassName!=null){
if (UnknownAccountException.class.getName().equals(exceptionClassName)) {
//最终会抛给异常处理器
throw new CustomException("账号不存在");
} else if (IncorrectCredentialsException.class.getName().equals(
exceptionClassName)) {
throw new CustomException("用户名/密码错误");
} else if("randomCodeError".equals(exceptionClassName)){
throw new CustomException("验证码错误");
}else if(AuthenticationException.class.getName().equals(exceptionClassName)){
throw new CustomException("认证失败");
}else{
throw new Exception();//最终在异常处理器生成未知错误
}
}else {
System.out.print("验证码输入不正确");
}
return "login";
}

}
40 changes: 37 additions & 3 deletions src/main/resources/spring/spring-shiro.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,29 @@
<property name="securityManager" ref="securityManager"/>
<!--loginUrl认证提交地址,如果没有认证将会请求此地址进行认证,请求此地址将由formAuthenticationFilter进行表单认证-->
<property name="loginUrl" value="/login"/>
<property name="successUrl" value="/homepage"/>

<!--自定义的filter-->
<property name="filters">
<map>
<!-- 将自定义 的FormAuthenticationFilter注入shiroFilter中 -->
<entry key="authc" value-ref="formAuthenticationFilter"/>
</map>
</property>


<!-- 过虑器链定义,从上向下顺序执行,一般将/**放在最下边 -->
<property name="filterChainDefinitions">
<value>
<!--对静态资源设置匿名访问-->
/images/**=anon
/js/**=anon
/style/**=anon
<!--/**=anon 表示所有的url都可以匿名访问,anon是shiro中一个过滤器的简写,关于shiro中的过滤器介绍见-->
/**=anon
/styles/**=anon
/resources/**=anon
/kaptcha**=anon
<!--/homepage=anon-->
<!-- -/**=authc 表示所有的url都必须认证通过才可以访问- -->
/**=authc
</value>
</property>
</bean>
Expand All @@ -26,6 +40,8 @@
<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="customRealm"/>
<!--注入会话管理器-->
<property name="sessionManager" ref="sessionManager"/>
</bean>

<!--自定义realm-->
Expand All @@ -41,4 +57,22 @@
<property name="hashAlgorithmName" value="md5" />
</bean>


<!--会话管理器-->
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<property name="sessionIdUrlRewritingEnabled" value="false" />
<!-- session的失效时长,单位毫秒 -->
<property name="globalSessionTimeout" value="600000"/>
<!-- 删除失效的session -->
<property name="deleteInvalidSessions" value="true"/>
</bean>

<!--自定义的from认证过滤器-->
<bean id="formAuthenticationFilter" class="filter.CustomFromAuthenticationFilter">
<!-- 表单中账号的input名称 -->
<property name="usernameParam" value="username"/>
<!-- 表单中密码的input名称 -->
<property name="passwordParam" value="password"/>
</bean>

</beans>
17 changes: 13 additions & 4 deletions src/main/resources/spring/spring-web.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
2).允许使用 "/" 做整体映射
-->
<mvc:default-servlet-handler/>
<mvc:resources mapping="/resources/**" location="resources/"/>
<mvc:resources mapping="/images/**" location="images"/>
<mvc:resources mapping="/js/**" location="js/"/>
<mvc:resources mapping="/styles/**" location="styles/"/>

<mvc:resources mapping="/resources/**" location="/resources/" />
<mvc:resources mapping="/images/**" location="/images/" />
<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:resources mapping="/styles/**" location="/styles/"/>

<!--3:配置JSP 显示ViewResolver-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
Expand All @@ -33,4 +34,12 @@
<context:component-scan base-package="web"/>
<context:component-scan base-package="kcaptcha"/>

<!--统一的异常处理器-->
<bean class="exception.CustomExceptionResolver"></bean>

<!-- 开启shiro注解支持 -->
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>

</beans>
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
</head>
<body>
<div align="center">
<h1>抱歉,您的登录认证失败</h1><br>
<h1>认证失败的异常信息:</h1><br>
${exception}
<h1>抱歉,登录失败</h1><br>
<h1>失败的异常信息:</h1><br>
${message}
</div>
</body>
</html>
Loading

0 comments on commit 2072d06

Please sign in to comment.