springmvc拦截器实现登录验证

首先创建一个实体类:

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>

 

posted @ 2018-09-17 21:43  小南天门  阅读(1880)  评论(0编辑  收藏  举报