springmvc拦截器实现登录验证

时间:2024-08-21 15:37:14

首先创建一个实体类:

Customer: 

 1 package com.petcare.pojo.base;
2
3 import java.sql.Date;
4 import java.sql.Timestamp;
5
6 /**
7 * Created by frank on 2017/5/7.
8 */
9
10 public class Customer {
11 private Long customerId;
12 private String account;
13 private String passwd;
14 private String customerName;
15 private String wechat;
16 private String mobile;
17
18 public Long getCustomerId() {
19 return customerId;
20 }
21 public void setCustomerId(Long customerId) {
22 this.customerId = customerId;
23 }
24 public String getAccount() {
25 return account;
26 }
27 public void setAccount(String account) {
28 this.account = account;
29 }
30 public String getPasswd() {
31 return passwd;
32 }
33 public void setPasswd(String passwd) {
34 this.passwd = passwd;
35 }
36 public String getCustomerName() {
37 return customerName;
38 }
39 public void setCustomerName(String customerName) {
40 this.customerName = customerName;
41 }
42 public String getWechat() {
43 return wechat;
44 }
45 public void setWechat(String wechat) {
46 this.wechat = wechat;
47 }
48 public String getMobile() {
49 return mobile;
50 }
51 public void setMobile(String mobile) {
52 this.mobile = mobile;
53 }
54
55 @Override
56 public boolean equals(Object o) {
57 if (this == o) return true;
58 if (o == null || getClass() != o.getClass()) return false;
59
60 Customer customer = (Customer) o;
61
62 if (customerId != customer.customerId) return false;
63 if (account != null ? !account.equals(customer.account) : customer.account != null) return false;
64 if (passwd != null ? !passwd.equals(customer.passwd) : customer.passwd != null) return false;
65 if (customerName != null ? !customerName.equals(customer.customerName) : customer.customerName != null)
66 return false;
67 if (wechat != null ? !wechat.equals(customer.wechat) : customer.wechat != null) return false;
68 if (mobile != null ? !mobile.equals(customer.mobile) : customer.mobile != null) return false;
69 if (homephone != null ? !homephone.equals(customer.homephone) : customer.homephone != null) return false;
70 if (customerSex != null ? !customerSex.equals(customer.customerSex) : customer.customerSex != null)
71 return false;
72 if (customerBirth != null ? !customerBirth.equals(customer.customerBirth) : customer.customerBirth != null)
73 return false;
74 if (address != null ? !address.equals(customer.address) : customer.address != null) return false;
75 if (createSeid != null ? !createSeid.equals(customer.createSeid) : customer.createSeid != null) return false;
76 if (createTime != null ? !createTime.equals(customer.createTime) : customer.createTime != null) return false;
77 if (updateTime != null ? !updateTime.equals(customer.updateTime) : customer.updateTime != null) return false;
78
79 return true;
80 }
81
82 @Override
83 public int hashCode() {
84 int result = (int) (customerId ^ (customerId >>> 32));
85 result = 31 * result + (account != null ? account.hashCode() : 0);
86 result = 31 * result + (passwd != null ? passwd.hashCode() : 0);
87 result = 31 * result + (customerName != null ? customerName.hashCode() : 0);
88 result = 31 * result + (wechat != null ? wechat.hashCode() : 0);
89 result = 31 * result + (mobile != null ? mobile.hashCode() : 0);
90 result = 31 * result + (homephone != null ? homephone.hashCode() : 0);
91 result = 31 * result + (customerSex != null ? customerSex.hashCode() : 0);
92 result = 31 * result + (customerBirth != null ? customerBirth.hashCode() : 0);
93 result = 31 * result + (address != null ? address.hashCode() : 0);
94 result = 31 * result + (createSeid != null ? createSeid.hashCode() : 0);
95 result = 31 * result + (createTime != null ? createTime.hashCode() : 0);
96 result = 31 * result + (updateTime != null ? updateTime.hashCode() : 0);
97 return result;
98 }
99 }

controller层;

 1 @Controller
2 public class LoginController {
3
4 private Logger log = LoggerFactory.getLogger(getClass());
5
6 public static final AjaxResponse ACCOUNT_NOT_EXIST = new AjaxResponse(-100101, "账号不存在");
7 public static final AjaxResponse PASSWORD_NOT_PASSED = new AjaxResponse(-100102, "您输入密码错误");
8 public static final AjaxResponse SYSTEM_BUSY = new AjaxResponse(-100000, "系统繁忙");
9 public static final AjaxResponse ACCOUNT_LOCKED = new AjaxResponse(-100103, "您的帐号被锁定");
10
11
12 @Autowired
13 private CustomerService customerService;
14
15 @RequestMapping(value = "/login", method = RequestMethod.GET)
16 public String loginPage(){
17 return "/login";
18 }
19
20 @RequestMapping(value = "/login", method = RequestMethod.POST)
21 @ResponseBody
22 public AjaxResponse login(String u , String p, HttpSession session){
23
24 // 封装令牌
25 UsernamePasswordToken token = new UsernamePasswordToken(u,p);
26 Subject subject = null;
27 try {
28 subject = SecurityUtils.getSubject();
29 // 用令牌登陆,如果登陆失败,则抛出异常
30 subject.login(token);
31 token.clear();
32 } catch (AccountNotExistException ex) {
33 return ACCOUNT_NOT_EXIST;
34 } catch (PasswordWrongException ex) {
35 return PASSWORD_NOT_PASSED;
36 }
37 catch (AccountLockedException ex) {
38 return ACCOUNT_LOCKED;
39 }
40 catch (Exception ex) {
41 log.error("login error happend.", ex);
42 return SYSTEM_BUSY;
43 }
44
45 Customer c = customerService.getBaseCustomer(u);
46
47 // 保存会话
48 session.setAttribute(Const.SESSION_SUBJECT, subject); // shiro已登录用户
49 session.setAttribute(Const.SESSION_USER_KEY,c );// 登陆用户
50 return AjaxResponse.OK;
51
52 }
53 }

UsernamePasswordToken源码:

package org.apache.shiro.authc;
/**
* Constructs a new UsernamePasswordToken encapsulating the username and password submitted
* during an authentication attempt, with a <tt>null</tt> {@link #getHost() host} and a
* <tt>rememberMe</tt> default of <tt>false</tt>.
*
* @param username the username submitted for authentication
* @param password the password character array submitted for authentication
*/
public UsernamePasswordToken(final String username, final char[] password) {
this(username, password, false, null);
} /**
* Constructs a new UsernamePasswordToken encapsulating the username and password submitted
* during an authentication attempt, with a <tt>null</tt> {@link #getHost() host} and
* a <tt>rememberMe</tt> default of <tt>false</tt>
* <p/>
* <p>This is a convience constructor and maintains the password internally via a character
* array, i.e. <tt>password.toCharArray();</tt>. Note that storing a password as a String
* in your code could have possible security implications as noted in the class JavaDoc.</p>
*
* @param username the username submitted for authentication
* @param password the password string submitted for authentication
*/
public UsernamePasswordToken(final String username, final String password) {
this(username, password != null ? password.toCharArray() : null, false, null);
}

getSubject()源码:

 1 package org.apache.shiro;
2
3 import org.apache.shiro.mgt.SecurityManager;
4 import org.apache.shiro.subject.Subject;
5 import org.apache.shiro.util.ThreadContext;
6
7
8 /**
9 * Accesses the currently accessible {@code Subject} for the calling code depending on runtime environment.
10 *
11 * @since 0.2
12 */
13 public abstract class SecurityUtils {
14
15 /**
16 * ONLY used as a 'backup' in VM Singleton environments (that is, standalone environments), since the
17 * ThreadContext should always be the primary source for Subject instances when possible.
18 */
19 private static SecurityManager securityManager;
20
21 /**
22 * Returns the currently accessible {@code Subject} available to the calling code depending on
23 * runtime environment.
24 * <p/>
25 * This method is provided as a way of obtaining a {@code Subject} without having to resort to
26 * implementation-specific methods. It also allows the Shiro team to change the underlying implementation of
27 * this method in the future depending on requirements/updates without affecting your code that uses it.
28 *
29 * @return the currently accessible {@code Subject} accessible to the calling code.
30 * @throws IllegalStateException if no {@link Subject Subject} instance or
31 * {@link SecurityManager SecurityManager} instance is available with which to obtain
32 * a {@code Subject}, which which is considered an invalid application configuration
33 * - a Subject should <em>always</em> be available to the caller.
34 */
35 public static Subject getSubject() {
36 Subject subject = ThreadContext.getSubject();
37 if (subject == null) {
38 subject = (new Subject.Builder()).buildSubject();
39 ThreadContext.bind(subject);
40 }
41 return subject;
42 }
43 }

login源码:

 1 /**
2 * Performs a login attempt for this Subject/user. If unsuccessful,
3 * an {@link AuthenticationException} is thrown, the subclass of which identifies why the attempt failed.
4 * If successful, the account data associated with the submitted principals/credentials will be
5 * associated with this {@code Subject} and the method will return quietly.
6 * <p/>
7 * Upon returning quietly, this {@code Subject} instance can be considered
8 * authenticated and {@link #getPrincipal() getPrincipal()} will be non-null and
9 * {@link #isAuthenticated() isAuthenticated()} will be {@code true}.
10 *
11 * @param token the token encapsulating the subject's principals and credentials to be passed to the
12 * Authentication subsystem for verification.
13 * @throws org.apache.shiro.authc.AuthenticationException
14 * if the authentication attempt fails.
15 * @since 0.9
16 */
17 void login(AuthenticationToken token) throws AuthenticationException;

clear源码:

 1 /*--------------------------------------------
2 | M E T H O D S |
3 ============================================*/
4
5 /**
6 * Clears out (nulls) the username, password, rememberMe, and inetAddress. The password bytes are explicitly set to
7 * <tt>0x00</tt> before nulling to eliminate the possibility of memory access at a later time.
8 */
9 public void clear() {
10 this.username = null;
11 this.host = null;
12 this.rememberMe = false;
13
14 if (this.password != null) {
15 for (int i = 0; i < password.length; i++) {
16 this.password[i] = 0x00;
17 }
18 this.password = null;
19 }
20
21 }

四个异常类,此时产生一个疑问,怎么验证数据那,此时需要一个配置我文件spring-shiro:

 1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"
4 xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
5 xmlns:context="http://www.springframework.org/schema/context"
6 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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/jee http://www.springframework.org/schema/jee/spring-jee-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/util http://www.springframework.org/schema/util/spring-util.xsd"
7 default-lazy-init="true">
8
9 <!-- 安全管理器 -->
10 <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
11 <property name="realm" ref="shiroDBRealm" />
12 <!--<property name="cacheManager" ref="cacheManager" />-->
13 </bean>
14 <!--<bean id="cacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager" />-->
15
16 <!-- shiro过滤器 -->
17 <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
18 <property name="securityManager" ref="securityManager" />
19 <property name="loginUrl" value="/login.action" />
20 <property name="successUrl" value="/welcome.action" />
21 <property name="unauthorizedUrl" value="/login.action" />
22 <property name="filterChainDefinitions">
23 <value>
24 </value>
25 </property>
26 </bean>
27 <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
28
29 <!-- 验证数据类 -->
30 <bean id="shiroDBRealm" class="com.petcare.admin.security.shiro.ShiroDBRealm" />
31
32 </beans>

类shiroDBRealm:

 1 /**
2 * Specl.com Inc.
3 * Copyright (c) 2010-2011 All Rights Reserved.
4 */
5 package com.petcare.admin.security.shiro;
6
7 import com.petcare.admin.service.CustomerService;
8 import com.petcare.pojo.base.Customer;
9 import org.apache.commons.lang.StringUtils;
10 import org.apache.shiro.authc.*;
11 import org.apache.shiro.authz.AuthorizationInfo;
12 import org.apache.shiro.authz.SimpleAuthorizationInfo;
13 import org.apache.shiro.realm.AuthorizingRealm;
14 import org.apache.shiro.subject.PrincipalCollection;
15 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory;
17
18 import javax.annotation.Resource;
19
20
21
22 /**
23 * 权限数据访问类。
24 *
25 *
26 */
27 public class ShiroDBRealm extends AuthorizingRealm {
28
29 private Logger log = LoggerFactory.getLogger(this.getClass());
30
31 /**
32 * 账号访问层。
33 */
34 @Resource
35 private CustomerService customerService;
36
37 /**
38 * 认证方法。
39 */
40 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
41
42 log.debug("do authentication ,token data [{}]", authcToken);
43
44 UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
45
46 if (token.getUsername() == null) {
47 return null;
48 }
49
50 // 根据账户名获得账户
51 Customer customer = customerService.getBaseCustomer(token.getUsername());
52
53 // 当账号密码不存在
54 if (customer == null) {
55 log.debug("customer not exist.");
56 throw new AccountNotExistException();
57 }
58
59 // 当密码错误
60 if (!StringUtils.equals(customer.getPasswd(), new String(token.getPassword()))) {
61 log.debug("password not equals.");
62 throw new PasswordWrongException();
63 }
64
65 // if(customer.getIsDelete()==1) {
66 // log.debug("customer is locked.");
67 // throw new AccountLockedException();
68 // }
69 return new SimpleAuthenticationInfo(customer.getAccount(), customer.getPasswd(), getName());
70 }
71
72 /**
73 * 授权方法。
74 */
75 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
76
77 log.debug("do authortization , principals data [{}]", principals);
78
79 // String username = (String) principals.fromRealm(getName()).iterator().next();
80 //
81 // // 根据账户名获得账户
82 // CustomerAccount account = customerAccountDao.getAccountByUsername(username);
83 //
84 // if (account == null) {
85 // log.debug("account not exist.");
86 // throw new AccountNotExistException();
87 // }
88
89 // 封装授权信息
90 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
91 // 将用户的角色字符,进行授权
92 // info.addRoles(account.getRoleStringList());
93 // 将用户的权限字符,进行授权
94 // info.addStringPermissions(account.getPermissionStringList());
95 return info;
96 }
97 }

web.xml:

有待修改:

 1     <!-- listeners -->
2 <listener>
3 <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
4 </listener>
5 <listener>
6 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
7 </listener>
8
9
10 <!-- shiro,find spring bean by filter name is 'shiroFilter' -->
11 <filter>
12 <filter-name>shiroFilter</filter-name>
13 <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
14 <init-param>
15 <param-name>targetFilterLifecycle</param-name>
16 <param-value>true</param-value>
17 </init-param>
18 </filter>