Shiro的使用

⦁ 配置web.xml


 <!-- 过滤器是Spring框架提供,用于整合shiro框架的 -->
 <!--而且这个过滤器一定要卸载struts过滤器之前 -->
 <!-- 项目启动过程中,在创建DelegatingFilterProxy过滤器的时候,需要应用一个同名的bean,这个bean必须在spring的配置文件中注册 -->
 <filter>
  <filter-name>shiroFilter</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
 </filter>
 <filter-mapping>
  <filter-name>shiroFilter</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>

⦁ 配置applicationContext.xml


 <!-- 注册shiro框架的工厂类,初始化框架提供的过滤器 -->
 <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
  <!-- 注入安全管理器 -->
  <property name="securityManager" ref="securityManager"></property>
  <!-- 登录页面 -->
  <property name="loginUrl" value="/login.html"></property>
  <!--登录成功以后跳转的页面 -->
  <property name="successUrl" value="/index.html"></property>
  <!-- 登录失败或者权限不足跳转的页面 -->
  <property name="unauthorizedUrl" value="/unauthorized.html"></property>
  <!-- 过滤规则 -->
  <property name="filterChainDefinitions">
   <!-- authc : 框架提供的过滤器,检查权限,如果有权限直接放行,没有权限,拒绝访问 -->
   <!-- anon : 框架提供的过滤器,可以进行匿名访问 -->
   <!-- 格式化代码的时候,规则不允许折行 -->
   <value>
    /css/* =anon
    /images/* =anon
    /js/** =anon
    /validatecode.jsp* = anon
    /** = authc
   </value>
  </property>
 </bean>
 <!--注册安全管理器 -->
 <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"></bean>

 ⦁ 在applicationContext.xml中配置realm
 <!--注册安全管理器 -->
 <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
  <property name="realm" ref="userRealm"></property>
 </bean>

⦁ 代码实现



⦁ 修改登录页面,为form表单增加action
 
⦁ 为登录的按钮绑定事件
 
⦁ 实现Action
@Namespace("/")
@ParentPackage("struts-default")
@Controller
@Scope("prototype")
public class UserAction extends CommonAction<User> {
    private static final long serialVersionUID = -885635712659668664L;
    public UserAction() {
        super(User.class);
    }
    // 登录操作
    @Action(value = "userAction_login",
            results = {
                    @Result(name = "success", location = "/index.html",
                            type = "redirect"),
                    @Result(name = "login", location = "/login.html",
                            type = "redirect")})
    public String login() {
        String serverCode = (String) ServletActionContext.getRequest()
                .getSession().getAttribute("key");
        if (StringUtils.isNotEmpty(serverCode)
                && StringUtils.isNotEmpty(validateCode)
                && serverCode.equals(validateCode)) {
            // subject代表当前的用户
            Subject subject = SecurityUtils.getSubject();
            // 创建令牌
            AuthenticationToken token = new UsernamePasswordToken(
                    getModel().getUsername(), getModel().getPassword());
            // 框架提供的登录方法
            try {
                subject.login(token);
   User user = (User) subject.getPrincipal();
                // 把用户存入Session
                ServletActionContext.getRequest().getSession()
                        .setAttribute("user", user);
                return SUCCESS;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return LOGIN;
    }
    // 使用属性驱动获取用户输入的验证码
    private String validateCode;
    public void setValidateCode(String validateCode) {
        this.validateCode = validateCode;
    }
}
⦁ 实现Realm
@Component
public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserRepository userRepository;
    // 授权方法
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(
            PrincipalCollection principals) {
        return null;
    }
    // 认证方法
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken usernamePasswordToken =
                (UsernamePasswordToken) token;
        // 通过用户名查找用户
        String username = usernamePasswordToken.getUsername();
        User user = userRepository.findByUsername(username);
        if (user == null) {
            // 没找到,抛异常
            return null;
        }
        /**
         * @param principal the 'primary' principal associated with the specified realm. 身份,一般出入当前用户
         * @param credentials the credentials that verify the given principal. 凭证,密码(是从数据库中获取到的密码)
         * @param realmName the realm from where the principal and credentials were acquired.
         *        realm的名字
         */
        AuthenticationInfo info = new SimpleAuthenticationInfo(user,
                user.getPassword(), getName());
        // 找到,比对密码,
        // 比对失败 : 抛异常
        // 比对成功 :
        return info;
    }
}
⦁ 实现DAO
public interface UserRepository extends JpaRepository<User, Long> {
    User findByUsername(String username);
}

项目1;

package com.newstrack.carhere.realm;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import com.newstrack.carhere.pojo.mysql.User;
import com.newstrack.carhere.service.PermissionService;
import com.newstrack.carhere.service.RoleService;
import com.newstrack.carhere.service.UserService;

/**
* @ClassName: MyRealm
* @Description: 自定义权限验证(没加盐)
* @author 
* @date 2018年1月29日 下午2:15:25

*/
public class MyRealm extends  AuthorizingRealm{
    @Autowired
    private UserService userService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private PermissionService permissionService;
    /**
     * 处理权限
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
      System.out.println("我进来了");
        User user = (User)principals.getPrimaryPrincipal();
           SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
           authorizationInfo.setRoles(roleService.findRoleByUserId(user.getId()));
           authorizationInfo.setStringPermissions(permissionService.findPermissionByUserId(user.getId()));
           return authorizationInfo;
    }
    /**
     * 认证方法
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
            throws AuthenticationException {
     //获取当前需要登录的用户
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String username = token.getUsername();
        //从数据库获取是否有对应的用户
        User user = userService.selectUser(username);
        if(user==null) {
         // 用户名不存在抛出异常
            throw new UnknownAccountException();
        }
        //MD5 加密+加盐+多次加密
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), this.getName());
        return info;
    }
}
 
controller;

package com.newstrack.carhere.controller;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMethod;
import com.alibaba.fastjson.JSONObject;
import com.newstrack.carhere.pojo.mysql.User;
import com.newstrack.carhere.service.UserService;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* @ClassName: UserController
* @Description: 用户模块接口
* @author 
* @date 2018年1月27日 下午3:03:43

*/
@CrossOrigin
@RestController
@RequestMapping(method = RequestMethod.POST)
public class UserController {
    @Autowired
    private UserService userService ;
    //创建一个json实例对象
    JSONObject jsonObject = new JSONObject(); 
   
    /**
    * @Title: checkLogin
    * @Description: 用户登录校验接口
    * @param @param 用户名
    * @param @param 密码
    * @param @param 设备ISM号
    * @param @return   
    * @return String 
    * @throws
    */
    @RequestMapping("login")
    public String checkLogin(@RequestBody(required=true)Map<String,String> map){
        String username = map.get("username").toString();
        String password = map.get("password").toString();
         Subject subject = SecurityUtils.getSubject();
        try {
         //创建用户名密码令牌
          AuthenticationToken token = new UsernamePasswordToken(username,password);
                subject.login(token);
                User user = (User) subject.getPrincipal();
                subject.getSession().setAttribute("user", user);
             jsonObject.put("status", "200"); 
             } catch (UnknownAccountException uae) {
                 // 捕获未知用户名异常
                 jsonObject.put("status", "400");
             } catch (IncorrectCredentialsException ice) {
              //捕获密码错误异常
               jsonObject.put("status", "450"); 
            } catch ( AuthenticationException ae ) {
           //不期望出现的错误  error?
              jsonObject.put("status", "500");
      }
         return jsonObject.toString();
    }
   
    /**
    * @Title: logout
    * @Description: 用户退出
    * @param @return   
    * @return String 
    * @throws
     */
    @RequestMapping("logout")
    public String logout(){
      Subject subject = SecurityUtils.getSubject();
         subject.logout();
         return jsonObject.put("status", "300").toString();
    }
   
    /**
    * @Title: findAll
    * @Description: 查询代理商下所有用户及下级代理商信息
    * @param @return   
    * @return List<User> 
    * @throws
     */
 
    @RequestMapping("user/findAll")
    public List<User> findAll(){
     Subject subject = SecurityUtils.getSubject();
     User user = (User) subject.getSession().getAttribute("user");
        return userService.findAll(user.getId());
    }
   
    /**
    * @Title: insertUser
    * @Description: 创建用户
    * @param @param user
    * @param @return   
    * @return String 
    * @throws
     */
    @RequestMapping(value = "user/insertUser")
 public String insertUser(User user){
  //查询是否用户名重复
  User selectUser = userService.selectUser(user.getUsername());
  if(selectUser!=null){
   jsonObject.put("status", "550"); 
  }
  String password = user.getPassword();
  //得到盐
  ByteSource salt=ByteSource.Util.bytes(user.getUsername());
  SimpleHash sh= new SimpleHash("MD5", password, salt, 1);
  user.setPassword(sh.toString());
  userService.insertUser(user);
  jsonObject.put("status", "600"); 
  return jsonObject.toString() ;
 }
   
    /**
    * @Title: updateUser
    * @Description: 更新用户信息
    * @param @param user
    * @param @return   
    * @return String 
    * @throws
     */
    @RequestMapping("user/updateUser")
    public String updateUser(@RequestBody(required=true)User user){
     if(StringUtils.isEmpty(user.getId())) {
      Subject subject = SecurityUtils.getSubject();
         User loginUser = (User) subject.getSession().getAttribute("user");
         user.setId(loginUser.getId());
     }
     userService.updateUser(user);
        return jsonObject.put("status", "650").toString(); 
    }
    /**
    * @Title: deleteUser
    * @Description: 删除用户信息
    * @param @param map
    * @param @return   
    * @return String 
    * @throws
     */
    @RequestMapping("user/deleteUser")
    public String deleteUser(@RequestBody(required=true)Map<String,String> map){
     String terminalID = map.get("terminalID").toString();
     userService.deleteUser(terminalID);
        return jsonObject.put("status", "750").toString(); 
    }
   
    @RequestMapping("user/test")
    public String test(){
        return jsonObject.put("status", 0).toString(); 
    }
}

applicationContext-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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
                        http://www.springframework.org/schema/mvc
                        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
    <!-- Realm实现 -->
    <bean id="userRealm" class="com.newstrack.carhere.realm.MyRealm">
        <property name="cachingEnabled" value="false"/>
        <property name="authenticationCachingEnabled" value="true"/>
        <property name="authenticationCacheName" value="authenticationCache"/>
        <property name="authorizationCachingEnabled" value="true"/>
        <property name="authorizationCacheName" value="authorizationCache"/>
    </bean>
   <!-- 配置ModularRealmAuthenticator,可以实现多Realm认证 -->
    <bean id="authenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
        <!-- 配置认证策略,只要有一个Realm认证成功即可,并且返回所有认证成功信息 -->
        <property name="authenticationStrategy">
            <bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean>
        </property>
    </bean>
    <!-- 会话ID生成器 -->
    <bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"/>
    <!-- 会话Cookie模板 -->
    <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        <constructor-arg value="sid"/>
        <property name="httpOnly" value="true"/>
        <property name="maxAge" value="180000"/>
    </bean>
    <!-- 会话DAO -->
    <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
        <property name="activeSessionsCacheName" value="shiro-activeSessionCache"/>
        <property name="sessionIdGenerator" ref="sessionIdGenerator"/>
    </bean>
    <!-- 会话验证调度器 -->
    <bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler">
        <property name="sessionValidationInterval" value="1800000"/>
        <property name="sessionManager" ref="sessionManager"/>
    </bean>
    <!-- 会话管理器 -->
    <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
        <property name="globalSessionTimeout" value="1800000"/>
        <property name="deleteInvalidSessions" value="true"/>
        <property name="sessionValidationSchedulerEnabled" value="true"/>
        <property name="sessionValidationScheduler" ref="sessionValidationScheduler"/>
        <property name="sessionDAO" ref="sessionDAO"/>
        <property name="sessionIdCookieEnabled" value="true"/>
        <property name="sessionIdCookie" ref="sessionIdCookie"/>
    </bean>
    <!-- 安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="authenticator" ref="authenticator"></property>
        <property name="realms">
            <list>
                <ref bean="userRealm" />
            </list>
        </property>
        <property name="cacheManager" ref="cacheManager"/>
    </bean>
    <!-- 缓存管理器开始 --> 
 <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> 
         <property name="cacheManagerConfigFile" value="classpath:spring/shiro-ehcache.xml"/> 
 </bean> 
 <!-- 缓存管理器结束 --> 
    <!-- Shiro过滤器 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> 
        <!-- Shiro的核心安全接口,这个属性是必须的 --> 
        <property name="securityManager" ref="securityManager"/>
        <!-- 身份认证失败,则跳转到登录页面的配置 --> 
        <property name="loginUrl" value="/index.jsp"/>
        <!-- 权限认证失败,则跳转到指定页面 --> 
        <property name="unauthorizedUrl" value="/index.jsp"/> 
        <!-- Shiro连接约束配置,即过滤链的定义 --> 
       <!-- 注入URL拦截规则 -->
  <property name="filterChainDefinitions">
    <value>
                <!-- 静态资源允许访问 -->
               /css/**=anon
            /iconfont/**=anon
            /images/**=anon
            <!--登录页面允许访问  -->
            /index.jsp = anon
               /login = anon
               <!-- 登录后须认证 -->
               /** = authc
               /user/**=roles[user]
            </value>
  </property>
    </bean> 
    
 <!-- 开启shiro框架注解支持 -->
 <bean id="defaultAdvisorAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
  depends-on="lifecycleBeanPostProcessor">
   <!-- 必须使用cglib方式为Action对象创建代理对象 -->
  <property name="proxyTargetClass" value="true"/>
 </bean>
 
 <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /> 
  
    <!-- 配置shiro框架提供的切面类,用于创建代理对象 -->
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> </bean>
</beans>

猜你喜欢

转载自blog.csdn.net/tomcatandoracle/article/details/80307044