This is the 27th day of my participation in the August More Text Challenge

1. Permission annotations

  • RequiresAuthentication: indicates that the current Subject has been authenticated by login; Subject. IsAuthenticated () returns true;

  • RequiresUser: indicates that the current Subject has authenticated or by remembering that I logged in;

  • RequiresGuest: Indicates that the current Subject is not authenticated or is a tourist by remembering that I logged in;

  • RequiresRoles (value={” admin “, “user”}, logical== logical. AND) : indicates that the current Subject RequiresRoles admin AND user, AND logical indicates logical relationships

  • ** @requirespermissions **(value={” user:a “, “user:b”}, logical= logical. OR) : Indicates that the current Subject needs permissions user:a OR user:b, logical indicates a logical relationship

Use:

/ / Service classes
public class TestService {
    @RequiresRoles({"admin"})
    public void testShiro(a){
        System.out.println("testShiro" + newDate()); }}Copy the code
<! -- applicationContext.xml -->
<bean id="testService" class="com.xiaojian.shiro.service.TestService"></bean>
Copy the code
@Controller
@RequestMapping("/shiro")
public class LoginController {

    @Resource
    private TestService testService;

    @RequestMapping("/testShiro")
    public String testShiroCon(a){
        testService.testShiro();
        return "redirect:/list.jsp"; }}Copy the code
<a href="/shiro/testShiro">Test Shiro</a>
Copy the code

Using the @Transactional annotation ona Service method means that a transaction occurs when the method begins, at which point the Service is already a proxy object

Adding permission annotations to a Service is not useful and can cause type casting exceptions. You need to add it to Controller because you can’t make a Service a proxy for a proxy.

2. Initialize resources and permissions from the database

As we implement authentication and authorization, we configure the paths to be authenticated or authorized in the applicationContext.xml file.

However, if there are too many authentication and authorization paths, it is too troublesome to configure paths one by one, and the files will be bloated and difficult to maintain.

(1). First write an instance factory class that returns a LinkedHashMap<String,String>

/** * Filter mapping set factory */
public class FilterChainDefinitionMapBuilder {
	/* * This allows you to query the list of roles and permissions from the database and assign values to filters instead of writing them manually */
    public LinkedHashMap<String,String> getFilterChainDefinitionMap(a){
        LinkedHashMap<String,String> hashMap = new LinkedHashMap<>();

        hashMap.put("/login.jsp"."anon");
        hashMap.put("/shiro/login"."anon");
        hashMap.put("/shiro/logout"."anon");
        hashMap.put("/user.jsp"."roles[user]");
        hashMap.put("/admin.jsp"."roles[admin]");
        hashMap.put("/ * *"."authc");

        returnhashMap; }}Copy the code

(2).applicationContext. XML, modify Shiro filter

   <! -- 5.Shiro filter ID must be the same as <filter-name> where DelegatingFilterProxy is configured in the web. XML file because Shiro queries the filter corresponding to <filter-name> in the IOC container bean -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <! Shiro's core security interface, this property is required -->
        <property name="securityManager" ref="securityManager"/>
        <! -- Authentication fails, skip to login page configuration -->
        <property name="loginUrl" value="/login.jsp"/>
        <property name="successUrl" value="success.jsp"/>
        <property name="unauthorizedUrl" value="unauth.jsp"/>

        <! FilterChainDefinitionMap Shiro connection constraint configuration (filterChainDefinitions)
        <property name="filterChainDefinitionMap" ref="filterChainDefinitionMap"></property>
    </bean>
    <! Configure a bean, which is a map, implemented through the instance factory class method -->
    <bean id="filterChainDefinitionMap" factory-bean="filterChainDefinitionMapBuilder" factory-method="getFilterChainDefinitionMap"></bean>

    <bean id="filterChainDefinitionMapBuilder" class="com.xiaojian.shiro.factory.FilterChainDefinitionMapBuilder"></bean>
Copy the code

3. Session management

Shiro provides complete enterprise-level session management functionality that is independent of the underlying container (such as Web container Tomcat) and can be used in both JavaSE and JavaEE environments. It provides session management, session event listening, session storage/persistence, container-independent clustering, invalidation/expiration support, transparent support for the Web, SSO SSO support and other features.

Why use Shiro’s session management?

In Web development, httpSession is generally not accessible at the Service layer (we do not recommend this, because accessing httpSession at the Service layer is a sneaked operation: the API in the Handler is used at the Service layer). Sessions can be accessed from anywhere using Shiro’s subject.getSession ().

The relevant API

  • Subject.getsession () : Get the session; This is equivalent to subject.getSession (true), that is, if no Session object is currently created, one will be created; Subject.getsession (false), which returns null if no Session is currently created

  • session.setAttribute(key, val) &

    session.getAttribute(key) &

    Session. removeAttribute(key) : Sets, obtains, and deletes session attributes. These properties can be manipulated throughout the session

  • Session.getid () : Obtains the unique identifier of the current session

  • Session.gethost () : Obtains the host address of the current Subject

  • Session.gettimeout () & session.setTimeout(ms) : Gets/sets the expiration time of the current session

  • Session. GetStartTimestamp () & session. GetLastAccessTime () : access to the session start time and the last access time; If the JavaSE application calls session.touch() periodically to update the last access time; For Web applications, session.touch() is automatically called every time ShiroFilter is entered to update the last access time.

  • Session.touch () & session.stop() : Update the last access time of the session and destroy the session; The stop method is automatically called when subject.logout () to destroy the session. If on the Web, calling httpsession.invalidate () also automatically calls shirosession.stop to destroy Shiro’s session

4, RememberMe

Check “RememberMe” when you log in to some web pages and the browser saves RememberMe cookies to the client.

When you close the browser and go back to the page, you don’t need to log in and go directly to the page.

Suggestion: Visit general webpage: personal homepage, can use remember me; Access to special web pages related to money, privacy, use of authentication.

Verify and remember me

  • Subject.isauthenticated () indicates that users are authenticated and logged in, even if subject.login isAuthenticated.
  • Subject.isremembered () : indicates that the user is logged in by remembering me and may not be the real you (for example, your friends are using your computer or your cookies have been stolen)
  • Choose one or the other: subject.isauthenticated () == true, and subject.isremembered () == false. And vice versa.

use

Authentication-related interceptors, user: user interceptors, users can authenticate/remember I login.

Shiro filter (User filter needs to be configured for paths accessible to RememberMe)

public class FilterChainDefinitionMapBuilder {

    public LinkedHashMap<String,String> getFilterChainDefinitionMap(a){
        LinkedHashMap<String,String> hashMap = new LinkedHashMap<>();
		// Configure the user filter
        hashMap.put("/list.jsp"."user");
        
        hashMap.put("/user.jsp"."authc,roles[user]");
        hashMap.put("/admin.jsp"."authc,roles[admin]");
        hashMap.put("/ * *"."authc");
        returnhashMap; }}Copy the code

LoginController.java

    @RequestMapping("/login")
    public String login(String username, String password,String checkbox, Model model){

        /** * Shiro certification */
        // 1. Get Subject
        Subject subject = SecurityUtils.getSubject();
        // 2. Encapsulate user information
        UsernamePasswordToken token = new UsernamePasswordToken(username,password);
        // Check whether "remember me" is selected and set the remember me function
        if("1".equals(checkbox)){
            token.setRememberMe(true); }... }Copy the code

applicationContext.xml

<! --1.SecurityManager SecurityManager --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="rememberMeManager" ref="rememberMeManager"/> </bean> <! Cookie implementation class SimpleCookie--> <bean id="simpleCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        <constructor-arg value="rememberMe"/>
        <property name="httpOnly" value="true"/>
        <property name="maxAge" value="120"/> </bean> <! --RememberMe manager --> <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
        <property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}"/>
        <property name="cookie" ref="simpleCookie"/>
    </bean>
Copy the code